2010-05-03 20 views
7

Tôi có một widget Qt mà chỉ nên chấp nhận một chuỗi hex như đầu vào. Nó rất đơn giản để hạn chế các ký tự nhập vào [0-9A-Fa-f], nhưng tôi muốn nó hiển thị với dấu phân cách giữa "byte", ví dụ nếu dấu phân tách là khoảng trắng và người dùng loại 0011223344 Tôi muốn chỉnh sửa dòng hiển thị 00 11 22 33 44 Bây giờ nếu người dùng nhấn phím xóa lùi 3 lần, sau đó tôi muốn nó hiển thị 00 11 22 3.QValidator cho đầu vào hex

I gần như có những gì tôi muốn, cho đến nay chỉ có một lỗi nhỏ liên quan đến việc sử dụng phím xóa để xóa dấu phân tách. Có ai có một cách tốt hơn để thực hiện validator này? Đây là mã của tôi cho đến thời điểm này:

class HexStringValidator : public QValidator { 
public: 
    HexStringValidator(QObject * parent) : QValidator(parent) {} 

public: 
    virtual void fixup(QString &input) const { 
     QString temp; 
     int index = 0; 

      // every 2 digits insert a space if they didn't explicitly type one 
     Q_FOREACH(QChar ch, input) { 
      if(std::isxdigit(ch.toAscii())) { 

       if(index != 0 && (index & 1) == 0) { 
        temp += ' '; 
       } 

       temp += ch.toUpper(); 
       ++index; 
      } 
     } 

     input = temp; 
    } 

    virtual State validate(QString &input, int &pos) const { 
     if(!input.isEmpty()) { 
      // TODO: can we detect if the char which was JUST deleted 
      // (if any was deleted) was a space? and special case this? 
      // as to not have the bug in this case? 

      const int char_pos = pos - input.left(pos).count(' '); 
      int chars   = 0; 
      fixup(input); 

      pos = 0; 

      while(chars != char_pos) { 
       if(input[pos] != ' ') { 
        ++chars; 
       } 
       ++pos; 
      } 

      // favor the right side of a space 
      if(input[pos] == ' ') { 
       ++pos; 
      } 
     } 
     return QValidator::Acceptable; 
    } 
}; 

Hiện tại mã này đủ chức năng, nhưng tôi muốn nó hoạt động 100% như mong đợi. Rõ ràng lý tưởng sẽ là chỉ riêng biệt màn hình hiển thị của chuỗi hex từ các ký tự thực tế được lưu trữ trong bộ đệm nội bộ của QLineEdit nhưng tôi không biết bắt đầu từ đâu và tôi tưởng tượng là một công việc không tầm thường.

Thực chất, tôi muốn có Trình xác thực phù hợp với regex này: "[0-9A-Fa-f]([0-9A-Fa-f])*" nhưng tôi không muốn người dùng phải nhập dấu cách làm dấu phân tách. Tương tự như vậy, khi chỉnh sửa những gì họ nhập, các không gian phải được quản lý hoàn toàn.

Trả lời

1

tôi sẽ đề xuất ba phương pháp:

Bạn có thể reimplement các QLineEdit::keyPressEvent() để xử lý dấu chéo ngược khác khi nhân vật chỉ còn lại để con trỏ 's QLineEdit là một không gian. Sử dụng phương pháp này, bạn cũng có thể tự động thêm dấu cách khi nhập một ký tự mới.

Cách tiếp cận khác là tạo một vị trí mới, được kết nối với tín hiệu QLineEdit::textChanged(). Tín hiệu này được phát ra khi văn bản được thay đổi. Trong khe này, bạn có thể xử lý việc tạo và xóa không gian phù hợp với nhu cầu của bạn.

Cuối cùng, bạn có thể tạo một lớp mới, bắt nguồn từ QLineEdit để thực hiện phương thức QLineEdit::paintEvent(). Với cách tiếp cận này, bạn có thể hiển thị không gian giữa các từ hex của bạn không được lưu trữ trong bộ đệm QLineEdit.

+0

Tôi tin rằng phương pháp thứ 3 là tối ưu, bạn có thể thấy ví dụ về mã như vậy không? –

+0

Bạn có thể xem http://websvn.kde.org/trunk/KDE/kdeutils/okteta/parts/kbytesedit/, dường như có liên quan (nhưng phức tạp hơn). – Lohrun

6

Evan, hãy thử này:

QLineEdit * edt = new QLineEdit(this); 
edt->setInputMask("Hh hh hh hh"); 

Các inputMask sẽ chăm sóc của khoảng cách, và "h" là viết tắt của một nhân vật hex tùy chọn ("H" cho một tổ chức phi tùy chọn). Chỉ có nhược điểm: Bạn phải biết trước thời lượng đầu vào tối đa. Ví dụ của tôi ở trên chỉ cho phép bốn byte.

Trân trọng, Robin

+0

Vâng, tôi cũng nghĩ đến việc sử dụng nó. Độ dài tối đa là một vấn đề mặc dù. Tôi ước tôi có thể nhận được hiệu ứng của mặt nạ đó, nhưng có thể nói nó lặp lại: - /. –