2013-04-06 14 views
10

Tôi có một QDialog với QDialogButtonBox. Các nút OKHủy đang hoạt động. Thỉnh thoảng tôi vô hiệu hóa hoặc ẩn nút OK dựa trên trạng thái hộp thoại của tôi. Dường như, bất kể tôi làm gì, phím Enter luôn kích hoạt nút OK. Tôi thực sự KHÔNG muốn điều này xảy ra. Tôi đã thử:Làm cách nào để ngăn khóa nhập đóng QDialog của tôi (Qt 4.8.1)

  • tính Setting mặc định và autoDefault false mỗi khi tôi hiển thị/ẩn/bật/tắt/bất cứ điều gì vào nút
  • cài đặt một bộ lọc sự kiện vào nút OK để đánh chặn các sự kiện quan trọng (nhấn và nhả) để trả lại, nhập và không gian
  • Thiết lập chính sách tập trung vào nút để NoFocus

và với tất cả sự kết hợp của những điều trên, phím Enter vẫn chấp nhận hộp thoại. Có ai có bất kỳ đầu mối làm thế nào để ngăn chặn điều này? Có vẻ như tôi có thể chặn thứ gì đó đơn giản như thế này?

+0

Bạn có thể gửi mã lọc bài sự kiện? –

+0

Đây có phải là hộp thoại của riêng bạn hoặc bạn nói về các hộp thoại tiêu chuẩn mà Qt cung cấp? – dtech

+0

Lớp hộp thoại của tôi – cppguy

Trả lời

7

Việc lọc sự kiện báo chí chính phải được thực hiện trên chính hộp thoại, vì mã xử lý việc chuyển tiếp các phím ReturnEnter đến nút mặc định nằm trong QDialog::keyPressEvent.

void Dialog::keyPressEvent(QKeyEvent *evt) 
{ 
    if(evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) 
     return; 
    QDialog::keyPressEvent(evt); 
} 

Hoặc

theDialog−>installEventFilter(anotherClassObject); 

bool AnotherClass::eventFilter(QObject *obj, QEvent *evt) 
{ 
    if(evt->type() == QEvent::KeyPress) { 
     QKeyEvent *keyEvent = static_cast<QKeyEvent*>(evt); 
     if(keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) 
      return true; // mark the event as handled 
    } 
    return false; 
} 
+0

tôi nên bỏ qua() sự kiện? – cppguy

+0

Điều này không hoạt động. Tôi không nhận được một cuộc gọi keyPressEvent trong lớp dựa trên QDialog của tôi khi Enter được nhấn. – cppguy

+2

Bạn không nên bỏ qua() sự kiện, nhưng chấp nhận nó và không làm gì cả. Nhưng nếu nút hủy vẫn được bật và có thể lấy nét, nó vẫn có thể được kích hoạt bằng phím Enter và đóng hộp thoại. – alexisdm

1

QDialog có một khe cắm tin gọi accept(). Bất cứ khi nào QDialogButtonBox phát ra accepted() (bằng cách bấm phím quay lại hoặc bấm Ok), khe riêng đó được gọi. Vì vậy, hãy thử ngắt kết nối chúng.

disconnect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));

Điều này làm việc cho tôi.

+0

Tôi chưa bao giờ thiết lập rõ ràng kết nối đó và đã xóa kết nối đó khỏi tệp ui trước đây – cppguy

-1

Trong PySide (và tôi tưởng tượng PyQt) tôi đã có thể xác định lại các chức năng chấp nhận và từ chối của QDialog.

def custom_accept(): 
    # perform custom actions when you hit open 
    pass 

def custom_reject(): 
    # perform custom actions when you hit cancel 
    pass 

file_dialog = QtGui.QFileDialog(directory=".") 
file_dialog.accept = custom_accept 
file_dialog.reject = custom_reject 

này giữ hộp thoại tập tin từ bế mạc và đã cho tôi quyền truy cập vào các dữ liệu khi 'ok' (chấp nhận) hoặc 'hủy' (từ chối) các chức năng được kích hoạt (hoặc với nhập hoặc bằng cách nhấn các nút)

1

Sự cố là bộ lọc sự kiện không được cài đặt trên nút OK.

Nếu nút OK của bạn bị vô hiệu hóa, nó sẽ không nhận được sự kiện nhập. Cho dù widget có tiêu điểm sẽ là gì. Và nếu họ không chấp nhận sự kiện nhập, thì QDialog sẽ tự động chuyển sang số accept().

Hai cách để giải quyết vấn đề:

1) Override QDialog::accept(), và gọi QDialog 's chấp nhận phương pháp trong accept chức năng mới chỉ nếu OK được kích hoạt

void MyDialog::accept() { 
    if (okEnabled) { 
     QDialog::accept(); 
    } 
} 

2) Cài đặt bộ lọc sự kiện trên mọi tiện ích trong hộp thoại không chấp nhận phím enter (chỉnh sửa dòng , ...).

Bộ lọc sự kiện sẽ như vậy:

class KeyPressEater : public QObject 
{ 
    Q_OBJECT 

protected: 
    bool eventFilter(QObject *obj, QEvent *event); 
}; 

bool KeyPressEater::eventFilter(QObject *obj, QEvent *event) 
{ 
    if (event->type() == QEvent::KeyPress) { 
     QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); 
     bool res = QObject::eventFilter(obj, event); 

     if (keyEvent->key() == Qt::Key_Return) { 
      return true; /* Always accept return */ 
     } else { 
      return res; 
     } 
    } else { 
     // standard event processing 
     return QObject::eventFilter(obj, event); 
    } 
} 

Và trong mã của bạn, cho mỗi widget trong hộp thoại:

myWidget->installEventFilter(myKeyPressEater); 
1

Nếu bạn có QPushButtons bình thường trên hộp thoại sau đó nếu các nút có các thuộc tính autoDefault và/hoặc mặc định được thiết lập trên chúng, sau đó bạn sẽ có một nút mặc định - đó là những gì mà phím enter sẽ kích hoạt. Trong trường hợp đó, loại bỏ autoDefault trên các nút và nhấn enter trong một widget khác không còn đóng hộp thoại nữa.

Trong trường hợp của QDialogButtonBox, bạn có thể lặp qua các nút để tắt nội dung này trong ctor của hộp thoại. Không được thử nghiệm ở đây nhưng phải làm việc. Nếu không thì bạn cũng sẽ cần phải xem nếu có một nút mặc định được thiết lập trên QDialog chính nó quá.

0

Để tránh nút "OK" hoặc phím "Enter" từ hộp thoại đóng: trong tệp xml ui, hãy xóa kết nối/khe để chấp nhận/từ chối. Sau đó, trong mã của bạn, emmit accept() khi nào và khi cần thiết;

ví dụ từ tập tin ui nối accept() khe:

<connections> 
    <connection> 

    <sender>products_ButtonBox</sender> 

    <signal>accepted()</signal> 

    <receiver>Products_Dialog</receiver> 
     <slot>accept()</slot> 
     <hints> 
     <hint type="sourcelabel"> 
     <x>248</x> 
     <y>254</y> 
     </hint> 
     <hint type="destinationlabel"> 
     <x>157</x> 
     <y>274</y> 
     </hint>e 
     </hints> 
     </connection>