当QLineEdit派生类处于禁用/只读状态时,如何隐藏操作按钮?
Nice catch on the limitations of overriding setDisabled/setReadOnly (since they're non-virtual) and the missing state change signals you noticed—let's walk through two reliable approaches to solve this:
Approach 1: Use Built-in State Change Signals (Recommended)
You might have missed that Qt provides signals for exactly these state changes! QWidget (which QLineEdit inherits from) has an enabledChanged(bool) signal, and QLineEdit itself has a readOnlyChanged(bool) signal. We can hook these up to a helper slot that updates the button's visibility.
First, add a private slot to your MyEdit class declaration:
class MyEdit : public QLineEdit { Q_OBJECT // ... your existing members ... private slots: void updateButtonVisibility(); };
Then, connect the signals in your constructor, right after setting up your action button:
MyEdit::MyEdit( QWidget *p_parent ) : QLineEdit( p_parent ) { // ... your existing initialization code ... // Connect state change signals to our helper slot connect(this, &QWidget::enabledChanged, this, &MyEdit::updateButtonVisibility); connect(this, &QLineEdit::readOnlyChanged, this, &MyEdit::updateButtonVisibility); }
Implement the slot to check all conditions (enabled, not read-only, and has completer data):
void MyEdit::updateButtonVisibility() { bool hasValidData = !m_sourceModel->data().isEmpty(); bool shouldShowButton = isEnabled() && !isReadOnly() && hasValidData; m_buttonAction->setVisible(shouldShowButton); }
Finally, update your setDataForCompleter method to reuse this slot instead of setting visibility directly:
void MyEdit::setDataForCompleter( const CompleterData &p_data ) { m_sourceModel->setCompleterData( p_data ); updateButtonVisibility(); // Let the slot handle visibility logic }
This approach is clean, follows Qt's signal-slot paradigm, and keeps all visibility logic in one place.
Approach 2: Override event() (For Older Qt Versions)
If you're working with a Qt version before 5.7 (where enabledChanged was added), you can override the event() method to catch state change events directly.
Add this override to your MyEdit class:
class MyEdit : public QLineEdit { Q_OBJECT // ... your existing members ... protected: bool event(QEvent *event) override; };
Implement the event() method to handle EnabledChange and ReadOnlyChange events:
bool MyEdit::event(QEvent *event) { // Check if we're handling a state change event if (event->type() == QEvent::EnabledChange || event->type() == QEvent::ReadOnlyChange) { updateButtonVisibility(); // Reuse the same slot from Approach 1! } // Always pass unhandled events to the parent class return QLineEdit::event(event); }
You can still use the same updateButtonVisibility slot from Approach 1 here—this just gives you a way to trigger it when state changes in older Qt versions.
Bonus: Ensure Initial State is Correct
Don't forget to set the initial visibility of the button in your constructor, right after creating it:
m_buttonAction->setVisible(false); // Start hidden updateButtonVisibility(); // Check initial state (in case the widget is created disabled/read-only)
内容的提问来源于stack exchange,提问作者songvan




