简体   繁体   中英

How to hide a temporary search bar?

I have a window that contains a browser. Up is a toolbar. In the bottom of the window is a search bar. Search bar has a close button [x]. When the user clicks the close button I want the bar to disappear. I want the bar only appear when user press CTRL + F. I tried to connect the close butoon with .hide() command, but application crashes. I need help.

在此处输入图片说明

.cpp

DocumentationWin::DocumentationWin (QWidget * parent){
    docs = new QTextBrowser( this );

    //Prepare toolbar
    toolbar = new QToolBar( this );
    //add stuff to toolbar


    //Prepare footer bar
    searchlabel = new QLabel(tr("Find in page:"),this);
    resultslabel = new QLabel("",this);
    searchinput = new QLineEdit();

    findprev = new QToolButton(this);
    findprev->setArrowType(Qt::UpArrow);
    connect(findprev, SIGNAL(clicked()), this, SLOT (clickFindPrev()));
    findnext = new QToolButton(this);
    findnext->setArrowType(Qt::DownArrow);
    connect(findnext, SIGNAL(clicked()), this, SLOT (clickFindNext()));

    QStyle *style = qApp->style();
    QIcon closeIcon = style->standardIcon(QStyle::SP_TitleBarCloseButton);
    QPushButton *closeButton = new QPushButton(this);
    closeButton->setIcon(closeIcon);
    closeButton->setFlat(true);
    connect(closeButton, SIGNAL(clicked()), this, SLOT (clickCloseFind()));
    QWidget *bottom = new QWidget;
    QHBoxLayout *footer = new QHBoxLayout();
    casecheckbox = new QCheckBox(tr("Case sensitive"),this);

    footer->setContentsMargins(5,5,5,5);
    footer->addWidget(searchlabel);
    footer->addSpacing(3);
    footer->addWidget(searchinput);
    footer->addWidget(findprev);
    footer->addWidget(findnext);
    footer->addSpacing(10);
    footer->addWidget(casecheckbox);
    footer->addSpacing(10);
    footer->addWidget(resultslabel);
    footer->addStretch(1);
    footer->addWidget(closeButton);
    bottom->setLayout(footer);


    //Prepare main layout
    layout = new QVBoxLayout;
    layout->setContentsMargins(0,0,0,0);
    layout->setSpacing(0);
    layout->addWidget(toolbar);
    layout->addWidget(docs);
    layout->addWidget(bottom);

    this->setLayout(layout);
    this->show();
}


void DocumentationWin::clickCloseFind(){
    bottom->hide();
}

.h

class DocumentationWin : public QDialog
{
  Q_OBJECT
  public:
    DocumentationWin(QWidget * parent);

  protected:
    virtual void keyPressEvent(QKeyEvent *);

  private slots:
    void clickCloseFind();

  private:
    QVBoxLayout* layout;
    QToolBar* toolbar;
    QTextBrowser* docs;
    QBoxLayout* footer;
    QLabel *searchlabel;
    QLabel *resultslabel;
    QLineEdit *searchinput;
    QToolButton *findprev;
    QToolButton *findnext;
    QCheckBox *casecheckbox;
    QWidget *bottom;
    QPushButton *closeButton;
};

Ahh, the classic case of local variables hiding the members. There have been quite a few identical questions on SO about this. This is wrong:

QWidget *bottom = new QWidget;

You want:

bottom = new QWidget;

You'll run into these problems always because you dynamically allocate all the widgets - that's completely unnecessary.

Suggestions:

  1. Hold the child widgets and layouts by value, don't dynamically allocate them.

  2. Don't pass a parent to widgets that are managed by a layout. Every widget that is laid out will be automatically parented.

  3. Don't redundantly call setLayout . A QLayout takes the widget to lay its children on as a constructor argument.

  4. QWidget::hide() is a slot.

  5. Many widgets take the text as a constructor argument.

  6. If you don't have any arguments to pass to the constructor in a new expression, you can drop the parentheses (but we try to avoid these anyway):

     searchinput = new QLineEdit; // not QLineEdit(); 
  7. Widgets shouldn't usually show() themselves upon construction. No Qt widget does that. It's up to the widget's user to do it.

  8. C++ overloads a method call syntax with construction syntax. To differentiate the two, prefer uniform initialization ( Type{arg0, arg1, ...} ) over old syntax that used () .

Here's how your code can look when you're using C++11. This compiles with either Qt 4 or Qt 5. If you don't target Qt 4, you should be using the new connect syntax, though.

As you can see, there isn't a single explicit dynamic allocation - that's how quite a bit of C++11 code will look, when the used types are sane.

// https://github.com/KubaO/stackoverflown/tree/master/questions/find-hide-38082794
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif

class DocumentationWin : public QDialog
{
   Q_OBJECT
public:
   explicit DocumentationWin(QWidget * parent = 0);
private:
   QVBoxLayout layout{this};
   QToolBar toolbar;
   QTextBrowser docs;
   QWidget bottom;
   QHBoxLayout footer{&bottom};
   QLabel searchlabel{tr("Find in page:")};
   QLabel resultslabel;
   QLineEdit searchinput;
   QToolButton findprev;
   QToolButton findnext;
   QCheckBox casecheckbox{tr("Case sensitive")};
   QPushButton closeButton;

   Q_SLOT void onFindPrev() {}
   Q_SLOT void onFindNext() {}
};

DocumentationWin::DocumentationWin(QWidget * parent) : QDialog(parent) {
   findprev.setArrowType(Qt::UpArrow);
   connect(&findprev, SIGNAL(clicked()), this, SLOT(onFindPrev()));
   findnext.setArrowType(Qt::DownArrow);
   connect(&findnext, SIGNAL(clicked()), this, SLOT(onFindNext()));

   auto style = qApp->style();
   auto closeIcon = style->standardIcon(QStyle::SP_TitleBarCloseButton);
   closeButton.setIcon(closeIcon);
   closeButton.setFlat(true);
   connect(&closeButton, SIGNAL(clicked(bool)), &bottom, SLOT(hide()));

   footer.setContentsMargins(5,5,5,5);
   footer.addWidget(&searchlabel);
   footer.addSpacing(3);
   footer.addWidget(&searchinput);
   footer.addWidget(&findprev);
   footer.addWidget(&findnext);
   footer.addSpacing(10);
   footer.addWidget(&casecheckbox);
   footer.addSpacing(10);
   footer.addWidget(&resultslabel);
   footer.addStretch(1);
   footer.addWidget(&closeButton);

   layout.setContentsMargins(0,0,0,0);
   layout.setSpacing(0);
   layout.addWidget(&toolbar);
   layout.addWidget(&docs);
   layout.addWidget(&bottom);
}

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   DocumentationWin win;
   win.show();
   return app.exec();
}

#include "main.moc"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM