如何隐藏临时搜索栏?
How to hide a temporary search bar?
我有一个包含浏览器的 window。向上是一个工具栏。 window 的底部是一个搜索栏。
搜索栏有一个关闭按钮 [x]。
当用户单击关闭按钮时,我希望该栏消失。
我希望该栏仅在用户按下 CTRL + F 时出现。我尝试使用 .hide() 命令连接关闭按钮,但应用程序崩溃了。我需要帮助。
.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;
};
啊,局部变量隐藏成员的经典案例。关于这个,SO 上有很多相同的问题。这是错误的:
QWidget *bottom = new QWidget;
你想要:
bottom = new QWidget;
您总是会 运行 陷入这些问题,因为您动态分配所有小部件 - 这是完全没有必要的。
建议:
按值保存子控件和布局,不要动态分配它们。
不要将父级传递给由布局管理的小部件。布置的每个小部件都将自动成为父级。
不要重复调用setLayout
。 QLayout
将要放置其子项的小部件作为构造函数参数。
QWidget::hide()
是一个插槽。
许多小部件将文本作为构造函数参数。
如果您没有任何参数要传递给 new
表达式中的构造函数,您可以去掉括号(但我们尽量避免这些):
searchinput = new QLineEdit; // not QLineEdit();
小部件通常不应该 show()
在构造时自己。没有 Qt 小部件可以做到这一点。这取决于小部件的用户。
C++ 用构造语法重载方法调用语法。为了区分这两者,更喜欢统一初始化 (Type{arg0, arg1, ...}
) 而不是使用 ()
.
的旧语法
以下是您使用 C++11 时代码的外观。这可以使用 Qt 4 或 Qt 5 进行编译。如果您不以 Qt 4 为目标,那么您应该使用新的连接语法。
如您所见,没有一个显式动态分配 - 当使用的类型正常时,C++11 代码看起来就是这样。
// https://github.com/KubaO/Whosebugn/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"
我有一个包含浏览器的 window。向上是一个工具栏。 window 的底部是一个搜索栏。 搜索栏有一个关闭按钮 [x]。 当用户单击关闭按钮时,我希望该栏消失。 我希望该栏仅在用户按下 CTRL + F 时出现。我尝试使用 .hide() 命令连接关闭按钮,但应用程序崩溃了。我需要帮助。
.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;
};
啊,局部变量隐藏成员的经典案例。关于这个,SO 上有很多相同的问题。这是错误的:
QWidget *bottom = new QWidget;
你想要:
bottom = new QWidget;
您总是会 运行 陷入这些问题,因为您动态分配所有小部件 - 这是完全没有必要的。
建议:
按值保存子控件和布局,不要动态分配它们。
不要将父级传递给由布局管理的小部件。布置的每个小部件都将自动成为父级。
不要重复调用
setLayout
。QLayout
将要放置其子项的小部件作为构造函数参数。QWidget::hide()
是一个插槽。许多小部件将文本作为构造函数参数。
如果您没有任何参数要传递给
new
表达式中的构造函数,您可以去掉括号(但我们尽量避免这些):searchinput = new QLineEdit; // not QLineEdit();
小部件通常不应该
show()
在构造时自己。没有 Qt 小部件可以做到这一点。这取决于小部件的用户。C++ 用构造语法重载方法调用语法。为了区分这两者,更喜欢统一初始化 (
Type{arg0, arg1, ...}
) 而不是使用()
. 的旧语法
以下是您使用 C++11 时代码的外观。这可以使用 Qt 4 或 Qt 5 进行编译。如果您不以 Qt 4 为目标,那么您应该使用新的连接语法。
如您所见,没有一个显式动态分配 - 当使用的类型正常时,C++11 代码看起来就是这样。
// https://github.com/KubaO/Whosebugn/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"