I am trying to add a label to the main window using Qt. Here is a piece of the code:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QWidget Main_Window;
QPixmap Image;
Image.load("1837.jpg");
QLabel i_label;
i_label.setPixmap(Image);
i_label.show();
QPushButton Bu_Quit("Quit", &Main_Window);
QObject::connect(&Bu_Quit, SIGNAL(clicked()), qApp, SLOT(quit()));
Main_Window.show();
return app.exec();
}
I've been having a very hard time figuring out how to properly add QLabels to QWidgets, I tried to set the Main_Window as the main widget using this method: app.setMainWidget(Main_Window) and the label was still outside the window. So how do I put labels into widgets using Qt?
hamza, this code worked fine for me:
#include <QtGui>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget Main_Window;
QLabel i_label("Start", &Main_Window);
//i_label.setPixmap(QPixmap("1837.jpg"));
QPushButton Bu_Quit("Quit" , &Main_Window);
QObject::connect(&Bu_Quit , SIGNAL(clicked()), qApp , SLOT(quit()));
QVBoxLayout *vbl = new QVBoxLayout(&Main_Window);
vbl->addWidget(&i_label);
vbl->addWidget(&Bu_Quit);
Main_Window.show();
return app.exec();
}
I commented setting the image code to show you that the label was set correctly. Make sure your image is valid (otherwise you won't see the text). The trick here was that you need to use qt layouts like QVBoxLayout
Add the label to a layout widget and set the window layout to that layout.
Design note: its better to create your own MainWindow class, inheriting from QMainWindow for instance, and design it from the inside.
or even better, use QtCreator.
You can try:
QWidget window;
QImage image("yourImage.png");
QImage newImage = image.scaled(150, 150, Qt::KeepAspectRatio);
QLabel label("label", &window);
label.setGeometry(100, 100, 100, 100);
label.setPixmap(QPixmap::fromImage(newImage));
window.show();
this way you can even decide where to put the label and choose the image size.
Related
I have QSplitter set as the central widget:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
mdiArea(new QMdiArea)
{
QWidget *widget = new QWidget;
widget->setMinimumSize(100, 100);
QSplitter *splitter = new QSplitter;
splitter->addWidget(mdiArea);
splitter->addWidget(widget);
setCentralWidget(splitter);
createActions();
}
void MainWindow::createSubwin()
{
QWidget *subwin = new QWidget(mdiArea);
subwin->setWindowTitle("Subwindow");
subwin->setMinimumSize(100, 100);
mdiArea->addSubWindow(subwin);
subwin->show();
}
void MainWindow::createActions()
{
QAction *actSub = new QAction("Add subwindow", this);
connect(actSub, SIGNAL(triggered()), SLOT(createSubwin()));
QMenu *winMenu = menuBar()->addMenu("Windows");
winMenu->addAction(actSub);
}
When I press maximize button of subwindow, the subwindow covers entire main window. Is there any way to prevent such behaviour and make subwindow occupy all the space of QMdiArea instead?
UPD: It looks like that the problem occurs only when at least one menu in main window's QMenuBar is present. Without menuBar everything works as expected:
https://www.qtcentre.org/threads/44457-QMdiSubWindow-maximizing-problem
Regarding the QSplitter, I gave OP the following hint:
Move the right part of the QSplitter into a dock widget (and drop the QSplitter), so that the left part is the only part of the QMainWindow::centralWidget(). This would mean to work with the existing class instead of against, and is probably easier to manage.
OP appreciated the hint with the dock widget but claimed the sub-window will still occupy the whole main window.
I must admit my lack of experience with MDI and made an MCVE to prove me myself right or wrong:
#include <QtWidgets>
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
QMainWindow qWinMain;
qWinMain.setWindowTitle("QMainWindow - MDI - Dock");
qWinMain.resize(640, 480);
// MDI
QMdiArea qMDI;
qWinMain.setCentralWidget(&qMDI);
// MDI sub widget
QLabel qWinSub("MDI Sub-Window\nwidget");
qMDI.addSubWindow(&qWinSub);
// Dock
QDockWidget qDock;
qDock.setWindowTitle("Dock");
QLabel qLblDock("Dock\nwidget");
qDock.setWidget(&qLblDock);
qWinMain.addDockWidget(Qt::RightDockWidgetArea, &qDock);
qWinMain.show();
// runtime loop
return app.exec();
}
Output:
So, I cannot reproduce OPs claim—it works on my side.
My platform: Windows 10, VS2019, Qt5.15
I enhanced the first MCVE a bit to see how it works if MDI sub-windows are created after qWinMain.show() (what's expected as the usual case).
#include <QtWidgets>
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
QMainWindow qWinMain;
qWinMain.setWindowTitle("QMainWindow - MDI - Dock");
qWinMain.resize(640, 480);
// MDI
QMdiArea qMDI;
qWinMain.setCentralWidget(&qMDI);
// Dock
QDockWidget qWinDock;
qWinDock.setWindowTitle("Dock");
QWidget qDock;
QVBoxLayout qVBoxDock;
QPushButton qBtnNewMDISubWin("New Sub-Window");
qVBoxDock.addWidget(&qBtnNewMDISubWin);
qDock.setLayout(&qVBoxDock);
qWinDock.setWidget(&qDock);
qWinMain.addDockWidget(Qt::RightDockWidgetArea, &qWinDock);
// create sub-window
int i = 0;
auto createSubWin = [&]() {
++i;
QLabel* pQWinSub = new QLabel(QString("MDI Sub-Window\nwidget %1").arg(i));
pQWinSub->setWindowTitle(QString("MDI Sub-Window %1").arg(i));
qMDI.addSubWindow(pQWinSub);
pQWinSub->show();
};
// install signal handlers
QObject::connect(&qBtnNewMDISubWin, &QPushButton::clicked,
createSubWin);
// runtime loop
qWinMain.show();
return app.exec();
}
Output:
It still works on my side as expected.
Note:
I had to add the explicit pQWinSub->show(); after qMDI.addSubWindow(pQWinSub); (which was not necessary in the first MCVE). However, this is exactly how it's done by OP's code.
OPs reply:
It turns out that the problem occurs only when menuBar is present
Oha. How comes?
I extended my MCVE again to add a menu bar:
#include <QtWidgets>
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
QMainWindow qWinMain;
qWinMain.setWindowTitle("QMainWindow - MDI - Dock");
qWinMain.resize(640, 480);
// menu
QMenuBar qMenuMain;
QAction qCmdFile("File");
QMenu qMenuFile;
QAction qCmdFileNew("New");
qMenuFile.addAction(&qCmdFileNew);
qCmdFile.setMenu(&qMenuFile);
qMenuMain.addAction(&qCmdFile);
qWinMain.setMenuBar(&qMenuMain);
// MDI
QMdiArea qMDI;
qWinMain.setCentralWidget(&qMDI);
// Dock
QDockWidget qWinDock;
qWinDock.setWindowTitle("Dock");
QWidget qDock;
QVBoxLayout qVBoxDock;
QPushButton qBtnNewMDISubWin("New Sub-Window");
qVBoxDock.addWidget(&qBtnNewMDISubWin);
qDock.setLayout(&qVBoxDock);
qWinDock.setWidget(&qDock);
qWinMain.addDockWidget(Qt::RightDockWidgetArea, &qWinDock);
// create sub-window
int i = 0;
auto createSubWin = [&]() {
++i;
QLabel* pQWinSub = new QLabel(QString("MDI Sub-Window\nwidget %1").arg(i));
pQWinSub->setWindowTitle(QString("MDI Sub-Window %1").arg(i));
pQWinSub->setFrameShape(QFrame::Box);
qMDI.addSubWindow(pQWinSub);
pQWinSub->show();
};
// install signal handlers
QObject::connect(&qCmdFileNew, &QAction::triggered,
createSubWin);
QObject::connect(&qBtnNewMDISubWin, &QPushButton::clicked,
createSubWin);
// runtime loop
qWinMain.show();
return app.exec();
}
Output:
Note:
I partly agree with OP:
Yes, the look of the maximized MDI is a bit different now. It looks like it occupies the whole client area of the main window but…
…the dock widget is still visible. I added a box to the QLabel (the top widget in the MDI sub-window) to illustrate this. In fact, the sub-window still occupies the central widget only (regardless what the look of its title bar suggests).
I'm trying to display a Q3DScatter graph in a Main Window designed with Qt Designer so I've added a widget to the main window but I don't know how to embed the graph object in this widget. I tried to create a widget "container" programmatically and embed the graph in it and then putting the widget in a QHBoxLayout (which has been added to the main window using Qt Designer) using the following code in my main window's constructor:
...
Q3DScatter *graph = new Q3DScatter();
QWidget *container = QWidget::createWindowContainer(graph);
ui->horizontal_layout->addWidget(container, 1);
But the window appears to be empty when executing. I'd really appreciate some help.
EDIT: Here's the full code of my main window constructor:
ResultsWindow::ResultsWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ResultsWindow)
{
ui->setupUi(this);
Q3DScatter *graph = new Q3DScatter();
QWidget *container = QWidget::createWindowContainer(graph);
ui->horizontal_layout->addWidget(container, 1);
}
And here's the main code:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ResultsWindow w;
w.show();
return a.exec();
}
EDIT 2: I forgot to specify that the horizontal layout is embedded in a GridLayout. I tried to create a new project and my code actually works perfectly when I add a horizontal layout directly to the main window. So could the problem be due to the GridLayout?
I am trying to get my container with a qquickview in it to be transparent, and only display the elements from the QML file without the background.
Is there a nicer way to implement this? Here is the relevant code, you can see I have commented out adding the QML to it so that the only offender is the QWidget containing a QQuickView
The QML will make a menu similar to Apple's "Cover Flow" using only text. I only want the text it generates to be visible.
Currently it has a solid white background.
QQuickView *view = new QQuickView();
QWidget *container = QWidget::createWindowContainer(view, this);
container->setObjectName("wrappingContainer");
container->setMinimumSize(1000, 240);
container->setMaximumSize(1000, 240);
container->setFocusPolicy(Qt::TabFocus);
//view->setSource(QUrl("qrc:/qml/wrappingMenu.qml"));
ui->testLayout->addWidget(container);
Try QQuickWidget:
#include <QtWidgets>
#include <QQuickWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget() {
setStyleSheet("background-color: 'grey';");
mQQuickWidget = new QQuickWidget(QUrl(QStringLiteral("main.qml")), this);
mQQuickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
mQQuickWidget->setAttribute(Qt::WA_AlwaysStackOnTop);
mQQuickWidget->setClearColor(Qt::transparent);
mQQuickWidget->resize(400, 400);
mQQuickWidget->raise();
}
private:
QQuickWidget *mQQuickWidget;
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
Widget widget;
widget.resize(400, 400);
widget.show();
return app.exec();
}
#include "main.moc"
main.qml:
import QtQuick 2.2
Item {
Text {
text: "Qt Quick Text"
font.pixelSize: 32
anchors.centerIn: parent
}
}
I doubt it could be done for a QQuickView embedded in a QWidget. But you can have a transparent QQuickView like :
QQuickView view;
view.setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format;
format.setAlphaBufferSize(8);
format.setRenderableType(QSurfaceFormat::OpenGL);
view.setFormat(format);
view.setColor(QColor(Qt::transparent));
view.setClearBeforeRendering(true);
view.setFlags(Qt::FramelessWindowHint);
view.setSource(QStringLiteral("qrc:/qml/wrappingMenu.qml"));
view.show();
You can do it with:
QQuickView view;
view.setColor(Qt::transparent);
view.setSource("main.qml");
I am having trouble getting a QGraphicsView to show up in a QVBoxLayout object and I have no idea what is wrong. My code compiles so no errors are being thrown. Here is my simple code. (I am a Qt and C++ newb). At the bottom, I add a QPushButton widget to the layout and that shows up fine. Thanks for your help in advance!
QGraphicsScene scene;
QGraphicsView view(&scene);
view.setBackgroundBrush(QImage(":/images/bg/tile.png"));
view.setCacheMode(QGraphicsView::CacheBackground);
QPixmap pixmap("images/icons/dsp.gif");
QGraphicsPixmapItem* dsp = scene.addPixmap(pixmap);
view.show();
vlayout->addWidget(&view);
vlayout->addWidget(new QPushButton("some button here"));
Not enough context, so I can't tell what's happening exactly. But, if those are in a function, then you are declaring local variables that are gone once the function exits. If you are in the main, you're code should look something like this, but it will probably crash:
QApplication app(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
QWidget widget;
view.setBackgroundBrush(Qt::red);
QVBoxLayout vlayout;
widget.setLayout(&vlayout);
vlayout.addWidget(&view);
vlayout.addWidget(new QPushButton("some button here"));
widget.show();
I recommend dynamically allocating objects:
int main(int argc, char* argv[]){
QApplication app(argc, argv);
QGraphicsScene* scene = new QGraphicsScene;
QGraphicsView* view = new QGraphicsView(scene);
QWidget *widget = new QWidget;
view->setBackgroundBrush(Qt::red);
QVBoxLayout* vlayout = new QVBoxLayout(widget);
vlayout->addWidget(view);
vlayout->addWidget(new QPushButton("some button here"));
widget->show();
return app.exec();
}
Don't forget to delete the parent object so it doesn't leak memory.
Basically, I want a simple pushButton with a colorful text which when pressed exits the application.
Why cant I press PushButton in this simple program. I am using QT 4.6 on Arch x86_64.
#include <QtGui/QApplication>
#include <QLabel>
#include <QPushButton>
#include<QtGui>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow *Main=new QMainWindow;
QPushButton *button = new QPushButton(Main);
QLabel *label = new QLabel(Main);
label->setText("<h2><i>Hello</i> ""<font color=red>Qt!</font></h2>");
label->setVisible(true);
QObject::connect(button, SIGNAL(clicked()),label, SLOT(close()));
label->setAlignment(Qt::AlignCenter|Qt::AlignVCenter);
label->setWindowTitle("HelloWorld Test Program");
Main->show();
return a.exec();
}
Beside the use of a button class that will allow you to display rich text, you also need to make sure your connections are correct.
In your example, you're connecting the clicked signal of the button to the clear() slot of the label, which is non-sense.
To exit your app when the button is clicked, you need to close the main window. Here is the code to get the right connection :
QObject::connect(button, SIGNAL(clicked()),Main, SLOT(close()));
Changing this single line of code in your example is not enough, because your label is drawn on top of your button, so it's not possible to graphically click on it. You need to hide your label and put some text into your button :
button->setText("Hello");
label->setVisible(false);
Regarding the rich text feature in a QPushButton, AFAIK it is not possible to do it with a QPushButton.
UPDATE :
Here is a way to put some richtext on a QPushButton. It uses the solution described by my comment : painting a QTextDocument onto a pixmap and setting this pixmap as the button's icon.
#include <QtGui/QApplication>
#include <QLabel>
#include <QPushButton>
#include <QtGui>
#include <QTextDocument>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow *Main=new QMainWindow;
QPushButton *button = new QPushButton(Main);
QTextDocument Text;
Text.setHtml("<h2><i>Hello</i> ""<font color=red>Qt!</font></h2>");
QPixmap pixmap(Text.size().width(), Text.size().height());
pixmap.fill( Qt::transparent );
QPainter painter( &pixmap );
Text.drawContents(&painter, pixmap.rect());
QIcon ButtonIcon(pixmap);
button->setIcon(ButtonIcon);
button->setIconSize(pixmap.rect().size());
QObject::connect(button, SIGNAL(clicked()),Main, SLOT(close()));
Main->show();
return a.exec();
}
Take a look here. Widget called QwwRichTextButton.
The QwwRichTextButton widget provides a button that can display rich text.