QPushButton Main Gui - qt

I'm beginning with Qt and I do not understand something. Here is my code:
#include <QApplication>
#include <QtWebKitWidgets/QWebView>
#include <QMainWindow>
#include <QPushButton>
QApplication a(argc, argv);
QMainWindow *mWin = new QMainWindow();
QPushButton *button = new QPushButton("Button");
button->setGeometry(0,0,128,56);
button->show();
mWin->setGeometry(QRect(300,300,1024,640));
mWin->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
mWin->show();
return a.exec();
When I launch the program, it makes a pushbutton, but not on the main GUI. It instead makes it in the upper lefthand corner of my scoeen. How do I make the pushbutton part of the main GUI?

Both QMainWindow and QPushButton derive from QWidget and generally, QWidgets can display themselves independently, so don't need to be attached to a parent, though it's likely you'll want to group and organise the widgets you're presenting to the user.
For a beginner, I think that QMainWindow is a bit misleading as you don't actually need it to display widgets. If, for example, you wanted to just display the button, you only need create the QPushButton and call show: -
QPushButton pButton = new QPushButton("Test");
pButton->show();
Though it's rare that you'll actually want to do this. In actuality, though it appears pointless, you can even just create a QWidget and display that: -
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.show();
return a.exec();
}
The QWidget can now be the parent to all other widgets, still without you defining a QMainWindow.
It is likely that you will want other widgets to display and Qt uses a parent / child hierarchy system of linking them together. Amongst other things, an advantage here is that you don't need to keep track of the different widgets in order to release their memory. When you're finished, you just delete the top level item, which may be a QMainWidget, or QDialog or other QWidget based object. In the case of Windows, all you need to do is close them and their children are cleaned up too.
Adding Widgets to a QMainWindow can be done in different ways, depending upon what you're trying to achieve. Eventually, you'll likely want to use layouts that allow grouping of widgets in logical arrangements, but to start with, if you look at the constructor of the QPushButton, you'll see that it takes an optional parameter of QWidget* : -
QPushButton(QWidget * parent = 0)
This allows you to attach the widget you're creating (QPushButton in this case) to a parent. Therefore, create the QMainWindow and then pass its pointer to the QPushButton.
QMainWindow* pWindow = new QMainWindow; // create the main window
QPushButton pButton = new QPushButton(pWindow); // create the push button
pWindow->show(); // Display the main window and its children.

You're creating a button and a window, but you're not associating them together. Therefore, the button is not part of the main UI. In order to add the button to the main window, you should add the following line-
mWin->setCentralWidget(button);
When creating user interfaces with Qt, it's better to avoid setting the geometry explicitly. Here is a nice page which describes the layouting in Qt.
Also, you seem to be missing a main function.

You are not setting parent child relationship, you need QPushbutton as a child of QMainwindow. Then you can see QPushbutton on QMainwindow.
Please try this, I am not sure what exactly you want to achive..but below code will give some hind about how to proceed..
QApplication a(argc, argv);
QMainWindow *mWin = new QMainWindow();
QPushButton *button = new QPushButton(mWin); // setting parent as QMainwindow
button->setGeometry(0,0,128,56);
// button->show();
//mWin->setCentralWidget( button );
mWin->setGeometry(QRect(300,300,1024,640));
mWin->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
mWin->show()
;

Create a central widget for the main window and then use a layout to place the push button on the central widget. For example:
QMainWindow *mWin = new QMainWindow();
// Place the button in a layout
QHBoxLayout *layout = new QHBoxLayout;
QPushButton *button = new QPushButton("Button");
layout->addWidget(button);
// Set up a central widget for the main window
QWidget *centralWidget = new QWidget();
centralWidget->setLayout(layout);
mWin->setCentralWidget(centralWidget);
If you've placed your button into a layout this way (or as a central widget itself, as one of the other answers has indicated), you don't need to set the geometry on the button, nor do you need to call setVisible or show on the button explicitly (but you still need to on the main window).
Consider looking through some of Qt's examples, such as the application example for more information.

Related

How to make a list of children widgets on a layout in QT?

A nice simple example would be nice. For my part, I wish to do something like this:
myLayout->addWidget(myButton1);
myLayout->addWidget(myButton2);
myButtonList<QToolButtons*>->append(myLayout->findChildren(QToolButtons));
myButtonList->at(1)->setText("This is 'myButton2'");
Use QList along with using findChildren with QWidget because QLayout does not show QWidgets as its children and a QWidget have a parent QWidget only. Refer this
QWidget w;
QPushButton *p1= new QPushButton;
QPushButton *p2= new QPushButton;
QHBoxLayout l;
l.addWidget(p1);
l.addWidget(p2);
w.setLayout(&l);
QList<QPushButton*> buttons = w.findChildren<QPushButton*>();
buttons.at(0)->setText("Hello I am P1");
buttons.at(1)->setText("Hello I am P2");
w.show();
A lot easier would be the approach to first fill the list and afterwards the layout:
QList<QToolButton *> list;
list.append(new QToolButton);
list.last().setText("1");
myLayout->addWidget(list.last());
This could then also be easily looped for a higher amount of buttons.
You can still use
ParentWidget->findChildren<QToolButtons *>();
edited given vahancho hint for parent is always a widget, not the layout

Quality of image deteriorates when used fitinview and Qt:KeepAspectRatio

I am using Qt and I want to display a image and I am displaying it in QGraphicsView and as the image is bigger than the dimensions of box of the QGraphicsView I used
ui->graphicsView->fitInView(viewraw->itemsBoundingRect() ,Qt::KeepAspectRatio);
where viewraw contains pixmap address to my image, my problem of oversized image was solved with this but my new problem now is the image after automatic resizing by Qt now shows with very very bad quality, it is very very blurry
What should I do?
Is there any way to display the image fit in the box and no quality loss?
Thank you!
You should try enabling antialiasing:
ui->graphicsView->setRenderHints(QPainter::Antialiasing
| QPainter::SmoothPixmapTransform
| QPainter::TextAntialiasing);
You can use QLayout::setSizeConstraint(QLayout::SetFixedSize) on the layout containing the view, to resize the parent widget to fit the view. The size will be the one returned by the view sceneRect() function.
For example, the following code will resize the QMainWindow (and lock the size) so that both items are visible:
#include <QtGui>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow mainWindow;
QGraphicsView *view = new QGraphicsView(&mainWindow);
QGraphicsScene *scene = new QGraphicsScene(view);
view->setScene(scene);
mainWindow.layout()->setSizeConstraint(QLayout::SetFixedSize);
mainWindow.setCentralWidget(view);
mainWindow.show();
scene->addRect(-100,-100,10,10, QPen(), Qt::red );
scene->addRect(600,450,10,10, QPen(), Qt::blue );
return a.exec();
}
Or, since you are using the designer,
in the widget tree, go to the parent item of the graphics view, it should have a layout,
if not (if the icon is this one: ), add one by left clicking on the item name and choose a layout in the "Lay Out" menu (if you only have one widget, the type of layout doesn't matter, just choose one),
then go to the last option in the property panel for the same item, which should be "layoutSizeConstraint" and select the option "SetFixedSize".

Qt alignment in QGridLayout eliminates the resizing of its elements

Ok, so basically I have a simple table with a QWidget and two buttons as shown below:
QGridLayout *layout = new QGridLayout;
layout->addWidget(viewcontainer,0,0,1,2);
layout->addWidget(reset,1,0);
layout->addWidget(done,1,1);
This is basically what I want, where "reset" and "done" are buttons. Essentially it's a QWidget, viewcontainer, which resizes as the window size is changed by the user while the buttons' heights remains the same. But, the default for the gridlayout is to align the contents to the left. If I change this with:
layout->addWidget(viewcontainer,0,0,1,2, Qt::AlignCenter);
It does sort of what I want, but the graphicsscene no longer resizes (remains a small constant size). I'd like to retain the resizing while just aligning the widget to the center. Thanks.
I think the easiest solution which provides a clean solution is to nest 2 layouts.
Your 'outer' (parent) layout should be a QHBoxLayout and you can add your QGridLayout into it as an 'inner' (child) layout with addLayout().
Based on my experience you should avoid to set Qt::Alignment every time you can. It can really mess up your layout. For simple layouts it can work but for more complex ones you should avoid it. And you never know that you should extend your layout in the future or not so my suggestion is to use nested layouts.
Of course you can create a QWidget for the 'outer' layout and for the 'innser' layout as well but most of the times it should be fine to just nest 2 layouts.
Also you can use QSpacerItem to fine-tune your layout.
Have a look at this example code, I think it does what you want:
#include <QApplication>
#include <QPushButton>
#include <QGraphicsView>
#include <QGridLayout>
#include <QPalette>
class MyWidget : public QWidget
{
public:
MyWidget()
{
QGridLayout * layout = new QGridLayout(this);
QGraphicsView * gv = new QGraphicsView;
layout->addWidget(gv, 0,0, 1,2);
layout->setRowStretch(0, 1); // make the top row get more space than the second row
layout->addWidget(new QPushButton("reset"), 1,0);
layout->addWidget(new QPushButton("done"), 1,1);
}
};
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
MyWidget w;
w.show();
return app.exec();
}

How to assign a signal to a QMenu instead of QAction in Qt?

I would like to have a menu item without children. I have a QMenubar, and in this menubar there is a QMenu. To use it as a menu, I have to put QActions in it, and they will appear if I click on the QMenu. How is it possible, to have only the menu, without any QActions, to do an action just as if it were a QAction?
A workaround would be to have a toolbox and disguise it as a menu, but it raises several problems:
It's not the cleanest solution
I have to manually care about highlighting it on mouse hover, and it will not be platform- and user setting independent.
I can't use it together in a menubar with normal menus with children.
So you want a menu bar that triggers actions without opening sub-menus?
Try to directly add QActions to the menubar, instead of having a QMenu inbetween:
#include <QtWidgets>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QMainWindow *wnd = new QMainWindow;
QMenuBar *m = new QMenuBar;
QAction *a = new QAction("DoIt");
QObject::connect(a, &QAction::triggered, [wnd](){
QMessageBox::information(wnd, "DoIt", "DoIt");
});
m->addAction(a);
wnd->setMenuBar(m);
wnd->show();
return app.exec();
}
Alternatively, you could subclass the QMenu and handle the mousePressEvent method to emit a signal

Qt Hide Taskbar Item

I have a custom QWidget and I simple don't want it to show up in the taskbar. I have a QSystemTrayIcon for managing exiting/minimizing etc.
I think the only thing you need here is some sort of parent placeholder widget. If you create your widget without a parent it is considered a top level window. But if you create it as a child of a top level window it is considered a child window und doesn't get a taskbar entry per se. The parent window, on the other hand, also doesn't get a taskbar entry because you never set it visible: This code here works for me:
class MyWindowWidget : public QWidget
{
public:
MyWindowWidget(QWidget *parent)
: QWidget(parent, Qt::Dialog)
{
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
MyWindowWidget widget(&window);
widget.show();
return app.exec();
}
No taskbar entry is ever shown, if this is want you intended.
Just set Qt::SubWindow flag for widget.
If you want to show/hide the widget without ever showing it at the taskbar your might check the windowflags of that widget. I'm not 100% sure, but I think I used Qt::Dialog | Qt::Tool and Qt::CustomizeWindowHint to achieve this, but my window wasn't fully decorated too. Another thing you might keep in mind if you play with that is the exit policy of your application. Closing/Hiding the last toplevel-window will normally exit your application, so maybe you need to call QApplication::setQuitOnLastWindowClosed(false) to prevent that...
Python code to achive this:
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class MainWindow(QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent, Qt.Tool)
window = MainWindow()
window.show()

Resources