【问题标题】:Issue with Qt Toolbar extension buttonQt 工具栏扩展按钮的问题
【发布时间】:2016-11-22 03:16:44
【问题描述】:

我必须在 Qt 中添加一个工具栏,如菜单栏下的 Windows 文件系统资源管理器之一(我在 Windows 7 下),这意味着当窗口宽度减小时,图标没有足够的位置显示会自动隐藏并放入下拉列表(单击工具栏右侧出现的箭头时会显示该下拉列表)。我首先将我找到的代码复制粘贴到网络上:

#include <QApplication>
#include <QAction>
#include <QMainWindow>
#include <QLineEdit>
#include <QToolBar>
#include <QHBoxLayout>



void initWindow(QMainWindow* w);


int main(int argc, char *argv[])
{
    Q_INIT_RESOURCE(application);

    QApplication app(argc, argv);

    QMainWindow mainWin;
    initWindow(&mainWin);
    mainWin.show();


    return app.exec();
}




void initWindow(QMainWindow* w)
{
    QLineEdit* searchBar = new QLineEdit;

    QAction* newAct = new QAction(QIcon(":/images/new.png"), "&New", w);
    newAct->setShortcuts(QKeySequence::New);

    QAction* openAct = new QAction(QIcon(":/images/open.png"), "&Open...", w);
    openAct->setShortcuts(QKeySequence::Open);

    QAction* saveAct = new QAction(QIcon(":/images/save.png"), "&Save", w);
    saveAct->setShortcuts(QKeySequence::Save);

    QAction* cutAct = new QAction(QIcon(":/images/cut.png"), "Cu&t", w);
    cutAct->setShortcuts(QKeySequence::Cut);

    QAction* copyAct = new QAction(QIcon(":/images/copy.png"), "&Copy", w);
    copyAct->setShortcuts(QKeySequence::Copy);

    QAction* pasteAct = new QAction(QIcon(":/images/paste.png"), "&Paste", w);
    pasteAct->setShortcuts(QKeySequence::Paste);


    QToolBar* fileToolBar = w->addToolBar("File");
    fileToolBar->addAction(newAct);
    fileToolBar->addAction(openAct);
    fileToolBar->addAction(saveAct);

    QToolBar* editToolBar = w->addToolBar("Edit");
    editToolBar->addAction(cutAct);
    editToolBar->addAction(copyAct);
    editToolBar->addAction(pasteAct);
    editToolBar->addWidget(searchBar);

}

...但问题是代码仅适用于 QMainWindow 中的工具栏(并使用 QMainWindow::addToolbar() 方法添加)。但是在我正在为之工作的代码中,我必须在 QWidget 而不是 QWindow 中这样做。所以我创建了一个水平布局,我在其中添加了几个小部件(一个 QLineEdit 和几个 QAction),它适用于 QAction 但不适用于 QLineEdit:当我点击箭头时,所有隐藏的 QAction 都是可见的,但不是 QLineEdit。这是我的代码:

#include <QApplication>
#include <QtGui/QWindow>
#include <QToolbar>
#include <QVBoxLayout>
#include <QMainWindow>
#include <QPushButton>
#include <QAction>
#include <QIcon>
#include <QLineEdit>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget* w = new QWidget;


    QHBoxLayout* tb1 = new QHBoxLayout;
    tb1->addWidget(new QPushButton("item11"));
    tb1->addWidget(new QPushButton("item12"));
    tb1->addWidget(new QPushButton("item13"));
    tb1->addWidget(new QPushButton("item14"));

    QHBoxLayout* spacerLayout = new QHBoxLayout;
    spacerLayout->addSpacerItem(new QSpacerItem(50, 20, QSizePolicy::MinimumExpanding,QSizePolicy::Fixed) );
    spacerLayout->setAlignment(Qt::AlignJustify);

    QWidget* sep = new QWidget;
    QRect rect = sep->geometry();
    rect.setWidth(0);
    sep->setGeometry(rect);
    QToolBar* tb3 = new QToolBar;
    QLineEdit* searchBar = new QLineEdit;
    QAction* item31 = new QAction(QIcon(":/images/cut.png"), "cut");
    QAction* item32 = new QAction(QIcon(":/images/copy.png"), "copy");
    QAction* item33 = new QAction(QIcon(":/images/open.png"), "open");
    QAction* item34 = new QAction(QIcon(":/images/paste.png"), "past");
    QAction* item35 = new QAction(QIcon(":/images/save.png"), "save");
    tb3->addWidget(sep);
    tb3->addWidget(searchBar);
    tb3->addAction(item31);
    tb3->addAction(item32);
    tb3->addAction(item33);
    tb3->addAction(item34);
    tb3->addAction(item35);

    QVBoxLayout* mainLayout = new QVBoxLayout;
    QHBoxLayout* topLayout = new QHBoxLayout;

    topLayout->addLayout(tb1);
    topLayout->addLayout(spacerLayout);
    topLayout->addWidget(tb3);


    QHBoxLayout* bottomLayout = new QHBoxLayout;
    bottomLayout->addWidget(new QPushButton);

    mainLayout->addLayout(topLayout);
    mainLayout->addLayout(bottomLayout);

    w->setLayout(mainLayout);
    w->show();

    return app.exec();
}

这些是第二种解决方案的结果截图:我第一次启动应用程序:

http://img4.hostingpics.net/pics/224120tb1.jpg

当我减小它的宽度时,右侧的小部件消失了。然后我点击箭头将它们显示到下拉列表中,除了 QLineEdit 之外,它们都显示:

http://img4.hostingpics.net/pics/903380tb2.jpg

这里有人知道问题是什么吗?谢谢。

【问题讨论】:

    标签: qt qtoolbar


    【解决方案1】:

    遗憾的是,工具栏只有在嵌入 QMainWindow 时才能正常工作。好消息是您可以像使用小部件一样使用 QMainWindow。您可以将其作为另一个小部件的父级,然后它将不是一个独立的窗口。我已经这样做了,而且效果很好。我使用 Qt Designer 创建对象,我不得不删除 QMainWindow 菜单栏,因为 Designer 会自动创建它。

    这不是一件直观的事情,但它工作得很好,而且它是一个相当容易的改变。一个写得很好的注释解释你为什么这样做可能会受到未来阅读代码的任何人的欢迎......

    【讨论】:

      【解决方案2】:

      感谢您的回答,我尝试使用 QMainWindow 进行测试,但它完全弄乱了我工作的布局,因为它是一个复杂的窗口(过去很多人都在使用它),我必须完成我的工作很快我宁愿尝试一种新的方法。因此,在对网络进行一些研究之后,我发现即使工具栏不在 QMainWindow 中,我也可以做到这一点,但我必须将我想要进入 QToolBar 的所有 QWidget 替换为 QWidgetAction 派生的类,并且将它们实例化为 QWidgetAction::createWidget() 方法。所以我做了这个工作正常的代码:

      main.cpp:

      #include <QApplication>
      #include <QtGui/QWindow>
      #include <QToolbar>
      #include <QVBoxLayout>
      #include <QMainWindow>
      #include <QPushButton>
      #include <QAction>
      #include <QIcon>
      #include <QLineEdit>
      #include <QSlider>
      #include <QVariant>
      #include <QCheckBox>
      #include <QWidgetAction>
      
      #include "QMyWidgetAction.h"
      
      
      void test2(QApplication& app);
      
      
      
      
      int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
          test2(app);
          return app.exec();
      }
      
      void test2(QApplication& app)
      {
      
          QWidget* w = new QWidget;
      
          QHBoxLayout* l1 = new QHBoxLayout;
          l1->addWidget(new QPushButton("item11"));
          l1->addWidget(new QPushButton("item12"));
          l1->addWidget(new QPushButton("item13"));
          l1->addWidget(new QPushButton("item14"));
      
          QHBoxLayout* l2 = new QHBoxLayout;
          l2->addSpacerItem(new QSpacerItem(50, 20, QSizePolicy::MinimumExpanding,QSizePolicy::Fixed) );
          l2->setAlignment(Qt::AlignJustify);
      
          QHBoxLayout* l3 = new QHBoxLayout;
          QToolBar* tb = new QToolBar;
          l3->addWidget(tb);
      
      
          QAction* item31 = new QAction(QIcon(":/images/cut.png"), "cut");
          QAction* item32 = new QAction(QIcon(":/images/copy.png"), "copy");
          QAction* item33 = new QAction(QIcon(":/images/open.png"), "open");
          QAction* item34 = new QAction(QIcon(":/images/paste.png"), "past");
          QAction* item35 = new QAction(QIcon(":/images/save.png"), "save");
          QLineEdit* searchBar = new QLineEdit;
          QMyWidgetAction* widgetAction = new QMyWidgetAction(tb);
          QLineEditAction* lineEditAction = new QLineEditAction(tb);
      
          tb->addSeparator();
          tb->addWidget(searchBar);
          tb->addAction(item31);
          tb->addAction(item32);
          tb->addAction(item33);
          tb->addAction(item34);
          tb->addAction(item35);
          tb->addAction(widgetAction);
          tb->addAction(lineEditAction);
      
          QVBoxLayout* mainLayout = new QVBoxLayout;
          QHBoxLayout* topLayout = new QHBoxLayout;
      
      
          topLayout->addLayout(l1);
          topLayout->addLayout(l2);
          topLayout->addLayout(l3);
      
      
          QHBoxLayout* bottomLayout = new QHBoxLayout;
          bottomLayout->addWidget(new QPushButton);
      
          mainLayout->addLayout(topLayout);
          mainLayout->addLayout(bottomLayout);
      
          w->setLayout(mainLayout);
          w->show();
      
      }
      

      QMyWidgetAction.h:

      #ifndef QMAYAWIDGETACTION_H
      #define QMAYAWIDGETACTION_H
      
      #include <QObject>
      #include <QWidget>
      
      #include <QWidgetAction>
      
      class QLineEdit;
      
      class QMyWidgetAction : public QWidgetAction
      {
          Q_OBJECT
      public:
          QMyWidgetAction(QWidget* parent);
          QWidget* createWidget(QWidget* parent);
      
      };
      
      
      class QLineEditAction : public QWidgetAction
      {
          Q_OBJECT
      public:
          QLineEditAction(QWidget* parent);
          QWidget* createWidget(QWidget* parent);
      
      protected slots:
          virtual void    searchTextChanged(const QString& text);
      
      private:
           QLineEdit* fWidget;
      
      };
      
      #endif // QMAYAWIDGETACTION_H
      

      QMyWidgetAction.cpp:

      #include <QApplication>
      #include <QtGui/QWindow>
      #include <QToolbar>
      #include <QVBoxLayout>
      #include <QMainWindow>
      #include <QPushButton>
      #include <QAction>
      #include <QIcon>
      #include <QLineEdit>
      #include <QSlider>
      #include <QVariant>
      #include <QCheckBox>
      #include <QWidgetAction>
      
      #include "QMyWidgetAction.h"
      
      
      QMyWidgetAction::QMyWidgetAction(QWidget* parent)
          : QWidgetAction(parent)
      {
      
      }
      
      
      QWidget* QMyWidgetAction::createWidget(QWidget* parent)
      {
          QPushButton* widget = new QPushButton("bouton", parent);
          widget->setMinimumSize(100, 30);
          return widget;
      }
      
      
      QLineEditAction::QLineEditAction(QWidget* parent)
          : QWidgetAction(parent)
      {
      
      }
      
      
      QWidget* QLineEditAction::createWidget(QWidget* parent)
      {
          fWidget = new QLineEdit(parent);
          connect(fWidget, SIGNAL(textChanged(QString)), this, SLOT(searchTextChanged(QString)));
          fWidget->setMinimumSize(100, 30);
          return fWidget;
      }
      
      
      void QLineEditAction::searchTextChanged(const QString& text)
      {
          fWidget->setMinimumWidth(fWidget->minimumWidth() + 10);
      }
      

      所以现在这是我减小窗口宽度时得到的结果:

      所以结果是正确的(并且控件有效,我对它们进行了测试),但现在我想知道是否可以水平显示扩展列表而不是垂直显示? (我的意思是“打开”操作右侧的“过去”操作,过去操作右侧的“保存”操作等)感谢您的帮助。

      【讨论】: