I need to place(programmaticaly) my custom widget in specified place in my MainWindow.
On screenshoot I've marked red rectangle "widget" on place where I want to place my widget. I want place widget on top of QmenuBar and QToolBar.
I've tried setCentralWidget, but it expands widget on whole window.
Image presenting my problem
Code of my widget:
timers.cpp
#include "QtWidgets"
#include "timers.h"
static QLabel *createDragLabel(const QString &text, QWidget *parent)
{
QLabel *label = new QLabel(text, parent);
label->setAutoFillBackground(true);
label->setFrameShape(QFrame::Panel);
label->setFrameShadow(QFrame::Raised);
return label;
}
Timers::Timers(QWidget *parent) : QWidget(parent)
{
QLabel *wordLabel = createDragLabel("dupppa", this);
}
mainwindow.cpp
MainWindow::MainWindow()
{
initMenu();
initButtons();
TrackWindow *trackWindow = new TrackWindow();
setCentralWidget(trackWindow);
Timers *firstTimer = new Timers();
//setCentralWidget(firstTimer); // suck
}
Ok, here is a solution: make MainWidget to be a parent of your widget but do not add it to parent layout. Then basically move your widget with QWidget::move() and and set its size with QWidget::resize(). This way you get a widget with absolute location.
An extract of working code:
#include <QLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow{ parent },
ui{ new Ui::MainWindow }
{
ui->setupUi(this);
menuBar = new QMenuBar { this };
toolBar = new QToolBar { this };
textEdit = new QTextEdit { this };
menuBar->addMenu("File");
menuBar->addMenu("Edit");
menuBar->addMenu("About");
toolBar->addAction("Copy");
toolBar->addAction("Cut");
toolBar->addAction("Insert");
toolBar->addAction("Other tools");
layout()->setMenuBar(menuBar);
addToolBar(toolBar);
textEdit->setText("Your widget");
textEdit->resize(90, 30);
textEdit->move(250, 10);
}
A screenshot:
Related
I have subclassed QWidget as follows:
class myClass : public QWidget
{
public:
explicit myClass(QWidget *parent);
protected:
void paintEvent(QPaintEvent *event);
}
myWidget::myWidget(QWidget* parent) : QWidget(parent)
{
setGeometry(10,10,100,100);
}
void myWidget::paintEvent(QPaintEvent *event)
{
QPainter qp(this);
QBrush bBlue(QColor::blue);
qp.fillRect(geometry(), bBlue);
}
What I wanted was to create a blue background QWidget placed onto the QWidget parent at 10,10 of size 100,100.
What I'm getting is a default size for myWidget of something like 100,50 at 0,0 with a black background (or transparent) and a blue rectangle starting at 10,10 within myWidget and clipped by myWidget.
It's like the setGeometry moved a rectangle within myWidget, not the myWidget itself.
Fairly new to Qt and would love an explanation and fix of above...
Thank you in advance.
Gary.
...here is actual code:
this is myWidget
class piTemplateWidget : public QWidget
{
public:
explicit piTemplateWidget(QWidget* parent);
static QColor* white;
static QColor* black;
static QColor* lightGrey;
static QColor* lightGreen;
piTemplate* tplt;
protected:
void paintEvent(QPaintEvent *event);
};
QColor* piTemplateWidget::white = new QColor(15,15,15);
QColor* piTemplateWidget::black = new QColor(250,250,250);
QColor* piTemplateWidget::lightGrey = new QColor(100,100,100);
QColor* piTemplateWidget::lightGreen = new QColor(250,15,250);
piTemplateWidget::piTemplateWidget(QWidget* parent) : QWidget(parent)
{
tplt = NULL;
move(100,100);
resize(300,240);
}
void piTemplateWidget::paintEvent(QPaintEvent *event)
{
QPainter qp(this);
QBrush bWhite(*white);
qp.fillRect(this->geometry(), bWhite);
// if (tplt==NULL)
// return;
// tplt->render(&qp);
}
...and this is the parent widgets constructor which instantiates my widget
piTemplateEdit::piTemplateEdit(QWidget *parent) :
QWidget(parent),
ui(new Ui::piTemplateEdit)
{
ui->setupUi(this);
currentTemplate = NULL;
if (piTemplate::templates->count()>0)
{
currentTemplate = (piTemplate*)piTemplate::templates->atIndex(0);
}
templateWidget = new piTemplateWidget(this);
templateWidget->tplt = currentTemplate;
}
...I hopes this helps.
Thank you.
Setting the geometry during the constructor may get overridden by the show event that the parent widget calls on it.
A common main function can look like this:
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
// w.showMaxmized(); // This line would trump the "setGeometry() call
// in the constructor
return a.exec();
}
The geometry rect stored in a QWidget is described here:
http://qt-project.org/doc/qt-4.8/application-windows.html
http://qt-project.org/doc/qt-4.8/qwidget.html#pos-prop
I would not use this internal QWidget setting as how you fill your widget. If you do want to store some setting, make a QRect member variable and use that instead.
If you want to fill the entire box of your QWidget with a color you should try something like this:
void myWidget::paintEvent(QPaintEvent *event)
{
QPainter qp(this);
QBrush bBlue(QColor::blue);
qp.fillRect(QRect(0,0, this->width(), this->height()), bBlue);
}
Inside paint functions, they are relative to paintable area you are in.
http://qt-project.org/doc/qt-4.8/qwidget.html#mapTo
And like #LaszloPapp was saying, you need to use resize() and move(). And it wouldn't hurt to throw in a update() call after either one of those.
Also be sure to check out the show() method and all of its "See Also" items.
http://qt-project.org/doc/qt-4.8/qwidget.html#show
http://qt-project.org/doc/qt-4.8/qshowevent.html
If you #include <QShowEvent>, and call resize() when the show event happens, you may be good to go. If you are nesting this widget inside another widget you should look into using the size hint and setFixedSize or using Layouts properly.
http://qt-project.org/doc/qt-4.8/layout.html
Hope that helps.
hi i create a dockwidget which i am starting it as hidden. The problem is that afterwards i cannot show it, while i can get the status correctly from the isHidden() function. The weird thing is that if i start the dockwidget not hidden, it works perfect. I am including an example that reproduces this strange behaviour.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void showDock();
private:
Ui::MainWindow *ui;
QDockWidget *dock;
QPushButton *button;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// QMainWindow mainWindow;
// QDockWidget *dock = new QDockWidget(&mainWindow);
QDialog *dockDialog = new QDialog(this); // <---------edit: you need to create a parent widget for the dock
dock = new QDockWidget(dockDialog);
dock->setStyleSheet("QDockWidget { font: bold }");
dock->setFloating(true);
dock->setFeatures(QDockWidget::DockWidgetVerticalTitleBar | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
QAbstractButton *floatButton = dock->findChild<QAbstractButton*>("qt_dockwidget_floatbutton");
if(floatButton)
floatButton->hide();
dock->setAllowedAreas( Qt::NoDockWidgetArea );
dock->setWindowTitle("Tools");
this->addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
QMainWindow *window = new QMainWindow(dock); // <------edit: set the dock to be the parent for the window
window->setWindowFlags(Qt::Widget);
QToolBar *bar = new QToolBar(window);
bar->setMovable(false);
bar->addAction("Select");
bar->addAction("Polygon");
bar->addAction("Brush");
bar->addAction("Erazer");
bar->addSeparator();
bar->addAction("Mark");
bar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
bar->setOrientation(Qt::Vertical);
window->addToolBar(Qt::LeftToolBarArea, bar);
window->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
window->setParent(dock);
dock->setWidget(window);
dock->hide(); // <------------ comment this line and it will work, edit: you do not need to do that anymore, it is working nicely now
button = new QPushButton("show", this);
button->setCheckable(true);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(showDock()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::showDock()
{
// qDebug() << "hello";
if(button->isChecked()){
if(dock->isHidden()){
qDebug() << "hidden";
dock->setFloating(true); // <-----edit: you need to add these lines in order to be able to see the dialog that contains the dock widget, i do not know why i need to that again since in the initialization i already specifying that my dock is floatable
QAbstractButton *floatButton = dock->findChild<QAbstractButton*>("qt_dockwidget_floatbutton"); // <---------edit: add this lines in order to get rid off the floating button
if(floatButton)
floatButton->hide(); // <----edit: the same as previous
dock->show();
}
}
if(!button->isChecked()){
if(!dock->isHidden()){
qDebug() << "not hidden";
dock->hide();
}
}
}
as it is now the above code the dockwidget is not appearing in the screen. If you try to comment the line that i am specifying in the mainwindow.cpp it works, but the point is that i want to start the dockwidget hidden. Does someone have any idea, of what is happening.
Thanks.
Parent of the QDock control should be your window widget, and not object of the MainWindow class.
So, you need to replace this:
dock = new QDockWidget(this);
with this:
QMainWindow *window = new QMainWindow(0); // I smell a potential leak here (set the parent!)
dock = new QDockWidget(window);
Control is visible when you press Show button in the first case, too, but it is somewhere outside the window, so you may not see it. Also, there is no need to create separate instance of QMainWindow inside class that is already inheriting QMainWindow.
I see you show()/hide() your dockwidget. I haven't tried it myself but maybe you should hide and show the dockwdiget with the QDockWidget::toggleViewAction method.
How can I create a QDialog with floating toolbar in Qt?
Attachment of the QMainWindow with toolbar as widget in the QDialog is not suitable.
Why not suitable? following code works like charms.
#include <QtGui>
class MyDialog : public QDialog
{
Q_OBJECT
public:
MyDialog(QWidget* parent=0)
{
QMainWindow* child = new QMainWindow;
QLabel* label = new QLabel(tr("QMainWindow with toolbar!"));
label->setAlignment(Qt::AlignCenter);
child->setCentralWidget(label);
QToolBar* toolbar = child->addToolBar(tr("Tool"));
toolbar->addAction(tr("Test"), this, SLOT(doTest()));
QHBoxLayout* layout = new QHBoxLayout(this);
layout->setContentsMargins(0,0,0,0);
layout->addWidget(child);
}
private slots:
void doTest()
{
QMessageBox::information(this, tr("Test"), tr("ToolBar is Working!"));
}
};
look at
Can you add a toolbar to QDialog?
and try to write smth like that
myDialog->layout()->setMenuBar(myToolBar);
I'm trying to create a menu in Qt following this example http://doc.qt.nokia.com/latest/mainwindows-menus.html
but I keep getting the error 'menuBar' not declared in this scope
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
In context:
#include <QtGui>
#include "borderlayout.h"
#include "window.h"
Window::Window()
{
QTextBrowser *centralWidget = new QTextBrowser;
//***Change this to whatever widget(s) the drawing area is. QPainter or something?
centralWidget->setPlainText(tr("DRAW HERE YAY"));
BorderLayout *layout = new BorderLayout;
layout->addWidget(centralWidget, BorderLayout::Center);
layout->addWidget(createLabel("File ..."), BorderLayout::North);
layout->addWidget(createLabel("Toolbar yo!"), BorderLayout::West);
//layout->addWidget(createLabel("Status bar"), BorderLayout::South);
//Maybe we could put in a status bar. For now let's not worry about it. It's not a requirement.
setLayout(layout);
createMenus();
setWindowTitle(tr("Border Layout"));
}
QLabel *Window::createLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setFrameStyle(QFrame::Box | QFrame::Raised);
return label;
}
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
window.h
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
class QLabel;
class QMenu;
class Window : public QWidget
{
Q_OBJECT
public:
Window();
private:
void createMenus();
QLabel *createLabel(const QString &text);
QMenu *saveMenu();
};
#endif
window.cpp
#include <QtGui>
#include "borderlayout.h"
#include "window.h"
Window::Window()
{
QTextBrowser *centralWidget = new QTextBrowser;
//***Change this to whatever widget(s) the drawing area is. QPainter or something?
centralWidget->setPlainText(tr("DRAW HERE YAY"));
BorderLayout *layout = new BorderLayout;
layout->addWidget(centralWidget, BorderLayout::Center);
layout->addWidget(createLabel("File ..."), BorderLayout::North);
layout->addWidget(createLabel("Toolbar yo!"), BorderLayout::West);
//layout->addWidget(createLabel("Status bar"), BorderLayout::South);
//Maybe we could put in a status bar. For now let's not worry about it. It's not a requirement.
setLayout(layout);
createMenus();
setWindowTitle(tr("Border Layout"));
}
QLabel *Window::createLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setFrameStyle(QFrame::Box | QFrame::Raised);
return label;
}
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
The menu bar is a feature of the QMainWindow class.
Because your Window class is being inherited directly from QWidget, it does not have the menuBar method, hence your error.
You need to subclass your Window class from QMainWindow rather than QWidget.
I have the following hierarchy in my Qt Application:
QMainWindow > QWidget (centralWidget) > QWidget (subclassed) > QLabel
Initialization code in my QMainWindow code:
centralWidget = new QWidget();
centralWidget->setGeometry(0,0,width,height);
chatWidget=new ChatWidget(this); // the subclassed QWidget
setCentralWidget(centralWidget);
In my subclassed QWidget initialization (which happens at the same time than the Qt App initialization) I have the following code:
ChatWidget::ChatWidget(QWidget *parent):QWidget(parent)
{
QLabel *lbl;
lbl=new QLabel(this);
lbl->setText("Hello World 1"); <-- Is properly Display
}
void ChatWidget::displayChatAfterButtonPressed()
{
QLabel *lbl;
lbl=new QLabel(this);
lbl->setText("Hello World 2"); <-- Does NOT appear
}
When the QLabel is added from the class initialization then the message is well displayed in the widget.
However when I launch the same code after a button pressed (via a function in the same QWidget subclass), then the text does not appear on screen.
I don't want to use layouts as I need to exactly position my labels.
Tried to repaint, but didn't help neither.
How can I properly and dynamically display a label after the initialization is done ?
Widgets when they are visible for the first time call to be visible to their children, but since you are creating it afterwards they probably are not calling that method, a possible solution is to call the show method.
void ChatWidget::displayChatAfterButtonPressed()
{
QLabel *lbl;
lbl=new QLabel(this);
lbl->setText("Hello World 2");
lbl->show();
}
comment: it seems strange to me that the QMainWindow you set a central widget and then create the chatWidget as a parent to the QMainWindow, it is generally not recommended to add children to the QMainWindow because it has a given structure, what should be done is to place it inside the centralwidget.
We need to show the label created by button click, cause centralwidget was already painted.
Here is a working example, I added this as answer also I noticed better adding chatWidget as child to centralWidget where in your original code its added to the UI .. this is your choice.
Mainwindow:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
//
ui->setupUi(this);
centralWidget = new QWidget();
centralWidget->setGeometry(width,height);
chatWidget=new ChatWidget(centralWidget); // the subclassed QWidget
setCentralWidget(centralWidget);
// added testing
QPushButton *btn = new QPushButton("MyButton",centralWidget);
btn->setGeometry(100,100,100,100);
btn->setMaximumSize(100,100);
connect(btn,&QPushButton::clicked, chatWidget, &ChatWidget::displayChatAfterButtonPressed);
}
and chatWidget:
ChatWidget::ChatWidget(QWidget *parent):QWidget(parent)
{
QLabel *lbl;
lbl=new QLabel(this);
lbl->setText("Hello World 1");
}
void ChatWidget::displayChatAfterButtonPressed()
{
QLabel *lbl;
lbl=new QLabel(this);
lbl->setText("Hello World 2");
lbl->show();
}