I have to add a toolbar in Qt like the Windows file system explorer one under menu bar (I'm under Windows 7) , that means when the window width is reduced, icons which don't have enough place to be displayed are automatically hidden and put into a drop down list (which is displayed when clicking to an arrow which appears to the toolbar's right side). I first copy paste a code that I found to the web :
#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);
}
... but the problem is that code works only for toolbars into a QMainWindow (and add by using QMainWindow::addToolbar() method). But into the code which I'm working for I have to do that into a QWidget, not a QWindow. So I created a horizontal layout, I added several widget into it (a QLineEdit and several QAction) and it works fine for QAction but not for QLineEdit : When I click to the arrow, all hidden QAction are visibles but not QLineEdit. Here is my code :
#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();
}
These are screenshots of the result with the 2nd solution : I first launch application :
http://img4.hostingpics.net/pics/224120tb1.jpg
When I reduce its width, widgets which are to the right side disapeared. Then I click to the arrow to display them into the drop down list and they are all displayed except the QLineEdit :
http://img4.hostingpics.net/pics/903380tb2.jpg
Is someone here knows what the problem is ? Thanks.
Regrettably, tool bars only function correctly when embedded in a QMainWindow. The good news is that you can use a QMainWindow as if it were a widget. You can parent it to another widget, and then it won't be a standalone window. I've done this, and it works well. I was creating the objects using Qt Designer, and I had to remove the QMainWindow menu bar because Designer creates that automatically.
It's not an intuitive thing to do, but it works just fine, and it's a fairly easy change. A well-written comment explaining why you did that would probably be welcomed by anyone else reading the code in the future...
Thank you for your answer, I tried to test with a QMainWindow but it completely messed up the layout on which I worked and as it's a complex window (a lot of people worked on it in the past) and I have to finish my work soon I preferred to try a new approach. So after some research on the web I found that it's possible to do that I want even if the toolbar is not into a QMainWindow, but I have to replace all QWidget's that I want to have into QToolBar by a class which derived of QWidgetAction's, and instantiate them into QWidgetAction::createWidget() method. So I did this code which works correctly :
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);
}
So now here is what I get when I reduce the window width :
So the result is correct (and controls works, I tested them), but now I would like to know if it's possible to display the extension list horizontally instead of vertically ? (I mean "past" action at the right of "open" action, "save" action at the right of past action etc.) Thanks for your help.
Below I present a full Qt project in which I was expecting to see a label and a button showing in a scrollarea, but it seems I'm not expressing myself as Qt expects. What Qt expects?
project.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = untitled13
TEMPLATE = app
SOURCES += main.cpp\
widget.cpp
HEADERS += widget.h
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QHBoxLayout>
#include <QScrollArea>
#include <QLabel>
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *mainLayout = new QHBoxLayout(this);
QScrollArea *scrollArea = new QScrollArea;
mainLayout->addWidget(scrollArea);
QWidget *widget = new QWidget;
scrollArea->setWidget(widget);
QHBoxLayout *hLayout = new QHBoxLayout;
widget->setLayout(hLayout);
QLabel *label = new QLabel("somelable");
hLayout->addWidget(label);
QPushButton *bt = new QPushButton("click");
hLayout->addWidget(bt);
}
Widget::~Widget()
{
}
In this specific code the problem is that you call
scrollArea->setWidget(widget);
before you add layout of the widget. Move the above mentioned call to the end of the constructor and you see the label and the button inside the scrollarea.
It's also mentioned in the QScrollArea::setWidget documentation:
Note that You must add the layout of widget before you call this
function; if you add it later, the widget will not be visible -
regardless of when you show() the scroll area.
I would like to use a custom made QWidget in one row of a QFormLayout. The code below presents a form layout in which the first row has a a QLineEdit and the second line has a custom made widget:
The problem is that the custom made widget is not vertically aligned. How to align it vertically?
project.pro:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = CustomLineEdit
TEMPLATE = app
SOURCES += main.cpp
main.cpp
#include <QApplication>
#include <QHBoxLayout>
#include <QFormLayout>
#include <QLineEdit>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QFormLayout *formLayout = new QFormLayout(&w);
QLineEdit *leUser = new QLineEdit;
QWidget *widget = new QWidget;
QHBoxLayout *hLayout = new QHBoxLayout(widget);
hLayout->addWidget(leUser);
hLayout->addWidget(new QPushButton);
formLayout->addRow("Text:", new QLineEdit);
formLayout->addRow("User:", widget);
w.show();
return a.exec();
}
This is because of margins. Just add followed line:
QHBoxLayout *hLayout = new QHBoxLayout(widget);
hLayout->setMargin(0); //this line
I have a QT main window and on top of this I want to add a widget ( containing buttons), as similar to image below.
If I add a dock widget , it is added in separate row, but not added as overlay on existing main window.
Any inputs ?
The easiest is to set your overlay widget's parent to be the main window. But because it will not be in any layout you have to take care of its geometry yourself. In case you want to have multiple overlays, the last added will be the top most.
#include <QApplication>
#include <QtGui>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow *window = new QMainWindow();
QWidget *centralWiddget = new QWidget();
window->setCentralWidget(centralWiddget);
QVBoxLayout *layout = new QVBoxLayout(centralWiddget);
QPushButton *button = new QPushButton("Button in a layout");
layout->addWidget(button);
QPushButton *overlayButton = new QPushButton("Button overlay");
overlayButton->setParent(window);
overlayButton->setGeometry(40, 40, 120, 30)
window->show();
return app.exec();
}
You should look into using QStackedLayout to so this.
I have a qlabel L inside a qwidget W. L is vertically and horizontally aligned.
When I resize W, L doesn't get centered.
Is this expected?
What's a good implementation to have L centered again?
To align text in a QLabel by calling QLabel::setAlignment works like expected for me.
Maybe you miss to add your Label to a Layout (so your label would automatically resized if your widget is resized). See also Layout Management. A minimal example:
#include <QApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QWidget>
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
QLabel* label=new QLabel("Hello World!");
label->setAlignment(Qt::AlignCenter);
QWidget* widget=new QWidget;
// create horizontal layout
QHBoxLayout* layout=new QHBoxLayout;
// and add label to it
layout->addWidget(label);
// set layout to widget
widget->setLayout(layout);
widget->show();
return app.exec();
}