2011-08-31 28 views
6

Nếu tôi gọi QCheckBox::setChecked(x) tín hiệu toggled chỉ phát ra nếu x không giống với trạng thái hộp kiểm hiện tại. Tôi hiểu logic đằng sau điều này, để tránh báo hiệu nếu không có gì thay đổi. Tuy nhiên, trong một số tình huống mà tôi có một thiết lập widget phức tạp hơn, tôi cần tín hiệu luôn được phát ra. Điều này đảm bảo bất kỳ ai đã kết nối với hộp kiểm sẽ nhận được trạng thái đầu tiên.Qt buộc QCheckBox phát ra tín hiệu trên setChecked

Có cách nào để có QCheckBox::setChecked(bool) phát ra tín hiệu bất kể trạng thái đã thay đổi không?


workaround đơn giản của tôi bây giờ là chỉ cần buộc các hộp kiểm thành nhiều tiểu bang bằng cách làm setChecked(!x)setChecked(x). Tôi đã hy vọng một cách chính xác hơn để làm điều này.

Trả lời

0

Một cách sẽ được phân lớp QCheckBox và thực hiện phát quang của tín hiệu ở chỗ, nơi bạn cần đến nó, ví dụ:

class MyCheckBox : public QCheckBox 
{ 
    Q_OBJECT 
public: 
    MyCheckBox(QWidget *parent = 0) : QCheckBox(parent) {}; 

    virtual void setChecked(bool checked) { 
      QCheckBox::setChecked(checked); emit checkWasSet(checked); 
      }; 
signals: 
    void checkWasSet(bool value); 

}; 

Bây giờ sử dụng lớp này thay vì lớp QCheckBox thường xuyên, và bạn có thể kết nối với tín hiệu checkWasSet() cho bất kỳ khi nào trạng thái kiểm tra được đặt.

+0

'setChecked' không phải là ảo trong 'QAbstractButton' (theo tài liệu).Thêm vào đó tôi muốn cơ chế là chung chung, cho bất kỳ cách nào mà trạng thái được thiết lập. Tôi cũng phải lặp lại các mô hình cho một số lớp khác (QCheckBox chỉ là ví dụ của tôi ở đây). –

6

Nhìn vào việc thực hiện QAbstractButton, tôi thấy dòng mã sau đây:

if (!d->checkable || d->checked == checked) { 
    if (!d->blockRefresh) 
     checkStateSet(); 
    return; 
} 

nơi checkStateSet là một chức năng ảo. QCheckBox ghi đè điều này và phát ra tín hiệu stateChanged() chỉ khi trạng thái thay đổi. Tôi chưa thử nghiệm điều này, nhưng tôi nghĩ rằng d->blockRefresh được đặt thành false nếu bạn gọi trực tiếp QCheckBox::setChecked(...).

Nếu đây là trường hợp, nó có nghĩa là bạn có thể phân lớp QCheckBox và ghi đè lên các phương pháp checkStateSet() một cái gì đó như thế này:

void MyCheckBox::checkStateSet() 
{ 
    QCheckBox::checkStateSet(); 
    if(m_oldState == checkState()) 
    { 
     // emit the signal here, as QCheckBox::checkStateSet() didn't do it. 
     emit stateChanged(m_oldState); 
    } 
    else 
    { 
     // don't emit the signal as it has been emitted already, 
     // but save the old state 
     m_oldState = checkState(); 
    } 
} 

nơi các tập tin tiêu đề chứa

private: 
    Qt::CheckState m_oldState; 

mà phải được khởi tạo vào Qt::Unchecked trong hàm tạo.

+0

Điều này có thể làm việc, nhưng phải phân lớp vì lý do này là một chút vấn đề: bạn phải nhớ trong thiết kế để thúc đẩy, và tất cả các lập trình viên phải nhớ sử dụng lớp này để thay thế. –

2

Dưới đây là một giải pháp mà có thể hoặc không có thể có thể cho trường hợp của bạn:

Nếu bạn có thể chắc chắn 100% rằng các tín hiệu và khe cắm của bạn được kết nối trước khi vào hộp kiểm có một cơ hội để thay đổi trạng thái của nó, mỗi kết nối lớp có thể khởi tạo một cách an toàn giả sử hộp kiểm không được chọn. Điều này là do các hộp kiểm luôn được bỏ chọn khi xây dựng. Bằng cách này, bạn có thể không phải gọi setChecked() sau khi kết nối các tín hiệu.

Tuy nhiên, cách tiếp cận này không hoạt động nếu có cơ hội tín hiệu được kết nối sau khi hộp kiểm đã thay đổi. Tôi không 100% thích cách tiếp cận này bản thân mình nhưng nó có thể là một lựa chọn cho bạn tuy nhiên.

0

Bạn có thể phát ra các tín hiệu với tình trạng hiện bản thân:

checkbox.stateChanged.emit(checkbox.checkState()) 
Các vấn đề liên quan