Previously I had difficulties creating a qt application with opengl, I always managed to create a pure opengl application with either SDL or glfw + glew.
But I followed the procedure everyone did in videos, created a class derived from QOpenGLWidget and promoted a widget to this class.
Today I decided to do it differently and it worked, first I created a class derived from QOpenGLWidget and QOpenGLFunctions as described in the qt documentation.
But instead of promoting my widget I used ui-> widget to get its reference in the layout and pass as parameter in the constructor of my class and it worked, at least it worked out well in parts ...
First of all I added a GridLayout to my window and the widget that was referenced inside the layout to better fit the user's screen. However only one piece of the widget is painted, at first I thought the opengl widget was changing the size of my widget, but I added a border through css to see if it was actually that but the widget was in the normal size according to figure:
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>656</width>
<height>350</height>
</rect>
</property>
<property name="windowTitle">
<string>Open 3D Texture Painter</string>
</property>
<property name="styleSheet">
<string notr="true">#m3dWorkspace{
border: 3px solid red;
}</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QWidget" name="m3dWorkspace" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>656</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="action_Settings"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="action_Settings">
<property name="text">
<string>&Settings</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
mainwindow.cpp
#include <QSettings>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "glworkspace.h"
#include "settings_window.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSettings settings(qApp->applicationDirPath() + "//settings.ini", QSettings::IniFormat);
settings.beginGroup("Render");
if(settings.value("renderApi", "ogl").toString() == "ogl"){
this->m_GLWorkspace = new GLWorkspace(ui->m3dWorkspace);
}else if(settings.value("renderApi", "ogl").toString() == "d3dx"){
///#todo setup render with DirectX
}else if(settings.value("renderApi", "ogl").toString() == "vk"){
///#todo setup render with vulkan
}
settings.endGroup();
this->m_SettingsWin = new SettingsWindow(this);
}
MainWindow::~MainWindow()
{
delete m_SettingsWin;
if(m_GLWorkspace != NULL){
delete m_GLWorkspace;
}
delete ui;
}
void MainWindow::on_action_Settings_triggered()
{
m_SettingsWin->exec();
}
glworkspace.h
#ifndef GLWORKSPACE_H
#define GLWORKSPACE_H
#include <QtOpenGL>
class GLWorkspace : public QOpenGLWidget, protected QOpenGLFunctions{
Q_OBJECT
public:
explicit GLWorkspace(QWidget *parent=0);
~GLWorkspace();
protected:
virtual void initializeGL() Q_DECL_OVERRIDE;
virtual void resizeGL(int w, int h) Q_DECL_OVERRIDE;
virtual void paintGL() Q_DECL_OVERRIDE;
private:
QOpenGLFunctions *m_F;
};
#endif // GLWORKSPACE_H
glwokspace.cpp
#include "glworkspace.h"
GLWorkspace::GLWorkspace(QWidget *parent) :
QOpenGLWidget(parent)
{
QSurfaceFormat format;
format.setVersion(4, 3);
format.setProfile(QSurfaceFormat::CoreProfile);
setFormat(format);
}
GLWorkspace::~GLWorkspace()
{
}
void GLWorkspace::initializeGL()
{
initializeOpenGLFunctions();
this->m_F = QOpenGLContext::currentContext()->functions();
m_F->glClearColor(0.0f, 1.0f, 0.5f, 0.0f);
}
void GLWorkspace::resizeGL(int w, int h)
{
m_F->glViewport(0, 0, w, h);
}
void GLWorkspace::paintGL()
{
m_F->glClear(GL_COLOR_BUFFER_BIT);
}
You forgot to add a layout on m3dWorkspace.
Add one, for example:
this->m_GLWorkspace = new GLWorkspace;
auto layout = new QVBoxLayout;
layout->addWidget(this->m_GLWorkspace);
ui->m3dWorkspace->setLayout(layout);
Related
I am trying to add a "new tab" on an existing QTabWidget using a QPushButton as shown below:
The problem I have is that as I push the button nothing happens and no "new tab" is added.
I set all the proper connection and slots but something is preventing me from adding it to the QTabWidget. Basically nothing happens as I push the button.
Below the minimal verifiable example:
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void newTab();
private slots:
void on_addTabBtn_clicked();
private:
Ui::MainWindow *ui;
};
mainwindow.cpp
#include <QLabel>
#include <QTabBar>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->tabWidget->clear();
ui->tabWidget->addTab(new QLabel("+"), QString("+"));
connect(ui->tabWidget, &QTabWidget::currentChanged, this, &MainWindow::on_addTabBtn_clicked);
newTab();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::newTab()
{
int position = ui->tabWidget->count() - 1;
ui->tabWidget->insertTab(position, new QLabel("Insert New Tab"), QString("New Tab"));
ui->tabWidget->setCurrentIndex(position);
auto tabBar = ui->tabWidget->tabBar();
tabBar->scroll(tabBar->width(), 0);
}
void MainWindow::on_addTabBtn_clicked()
{
int index = 0;
if(index == this->ui->tabWidget->count() - 1) {
newTab();
}
}
In case you would also like to see the simple .ui file see below:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>428</width>
<height>279</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Tab 1</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Tab 2</string>
</attribute>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="addTabBtn">
<property name="text">
<string>Add Tab</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>428</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
I tried to solve the problem in many ways and researched what the cause might be. I came across several references such as this one, this and also this one but none of them helped to completely solve the problem.
I am sure that the property of currentChanged is correct, however the callback to trigger the button is not doing the job despite there are no errors in the terminal.
What am I missing? Thanks for pointing to the right direction for solving this issue.
connect the clicked signal of the button to the addTab function/slot of the tabwidget (or to an intermediate function/lambda that calls addTab on the correct destination object).
For example:
connect(ui->addTabBtn, &QPushButton::clicked, this, [&] { ui->tabWidget->addTab(new QLabel("+"), QString("+")); });
Or something along those lines.
Im working on a simple project in QtCreator where you input text into a line_edit which then gets printed after clicking a button. It works but I need to resize the window in order to see the updated/changed display.
So starting off with the main.cpp, I have left it as default after some tests:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
That has the issue I was talking about above. I decided to add w.update(); and see if that fixed the issue, it did not. I thought maybe it was because the program was not looping, so I entered the code in a while(true) loop which also was to no avail.
The mainwindow.cpp file is as follows:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->textBtn, SIGNAL(clicked(bool)), this, SLOT(setText()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setText()
{
QString temp = ui->inputText->text();
ui->displayLabel->setText(temp);
}
MainWindow.hpp:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void setText();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Is there a QObject or predifined function in QT that allows me to update the window or automatically updates the window after a detected user change?
Edit: The UI file might be of importance as well:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>554</width>
<height>463</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLabel" name="displayLabel">
<property name="geometry">
<rect>
<x>140</x>
<y>150</y>
<width>251</width>
<height>91</height>
</rect>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>130</x>
<y>30</y>
<width>251</width>
<height>81</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="inputText"/>
</item>
<item>
<widget class="QPushButton" name="textBtn">
<property name="text">
<string>Display Text</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>554</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
The problem is not the update of the GUI but the QLabel does not change size, the initial size depends on the initial text, and if you set a text with larger size only part of the text will be displayed. To adjust the size of the label to the size of the text you must use adjustSize():
void MainWindow::setText()
{
QString temp = ui->inputText->text();
ui->displayLabel->setText(temp);
ui->displayLabel->adjustSize();
}
On the other hand in Qt5 it is advisable to use the new connection syntax since they have several advantages as indicated by the docs, in your case you must change your code to:
connect(ui->textBtn, &QPushButton::clicked, this, &MainWindow::setText);
I'm new to QT and now facing a problem with function QImage::setPixel and QPainter::drawPoint
I have mainwindow and a widget in it, called drawing area. The drawing area using layout with a label in it, which contains QImage converted to QPixmap. Unfortunately the functions I use to draw points give no result.
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
area = new DrawingArea(this);
area->setGeometry(0,0,this->width(),this->height()/2);
area->show();
button = new QPushButton("Draw", this);
int bwidth = 100, bheight = 50;
button->setGeometry(200, 300, bwidth, bheight);
connect(button, SIGNAL(clicked(bool)), this, SLOT(getPoint()));
}
MainWindow::~MainWindow()
{
delete ui;
delete button;
delete area;
}
void MainWindow::getPoint(){
area->clearPoints();
area->makePoint(ui->textEdit->toPlainText().toInt(), ui->textEdit_2-
>toPlainText().toInt());
area->makePoint(ui->textEdit_3->toPlainText().toInt(), ui->textEdit_4-
>toPlainText().toInt());
area->makePoint(ui->textEdit_5->toPlainText().toInt(), ui->textEdit_6-
>toPlainText().toInt());
area->showPoints();
}
DrawinArea.cpp
#include "drawingarea.h"
#include <QHBoxLayout>
#include <QPen>
#include <QPainter>
DrawingArea::DrawingArea(QWidget *parent) : QWidget(parent)
{
setBackgroundRole(QPalette::Base);
setAutoFillBackground(true);
canvas = new QImage(600, 500, QImage::Format_RGB32);
QRgb val = qRgb(189,149,39);
canvas->fill(Qt::gray);
canvas->setPixel(4,4,val);
canvas->setPixel(5,4,val);
imgDisplayer = new QLabel;
imgDisplayer->setPixmap(QPixmap::fromImage(*canvas));
displayer = new QLabel;
auto *layout = new QHBoxLayout(this);
layout->addWidget(imgDisplayer);
layout->addWidget(displayer);
}
void DrawingArea::paintEvent(QPaintEvent * /* event */){
//
}
void DrawingArea::clearPoints(){
points.clear();
}
void DrawingArea::makePoint(int x, int y){
Point *temp = new Point(x,y);
points.push_back(*temp);
free(temp);
}
void DrawingArea::showPoints(){
displayer->clear();
QPainter painter(canvas);
QPen pen;
pen.setWidth(1);
pen.setColor(Qt::red);
painter.setBrush(Qt::NoBrush);
painter.setPen(pen);
painter.end();
QString text;
for(size_t i = 0; i < points.size();i++){
text+= ("P" + QString::number(i) + " (X: " +
QString::number(points[i].x) +
"; Y: " + QString::number(points[i].y) + ");\n");
painter.drawPoint(points[i].x, points[i].y);
}
imgDisplayer->setPixmap(QPixmap::fromImage(*canvas));
displayer->setText(text);
displayer->setGeometry(300, 80, 100,100);
displayer->show();
imgDisplayer->show();
}
DrawingArea::~DrawingArea(){
delete canvas;
delete displayer;
delete imgDisplayer;
}
Here is a minimal example. Hope that helps :)
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QImage>
#include <QPainter>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->drawButton, &QPushButton::clicked, [=](){ // Lambda to keep example small. You may also just have a own method
auto x = ui->xLineEdit->text().toInt();
auto y = ui->yLineEdit->text().toInt();
const QPixmap *pixmap = ui->imageLabel->pixmap();
QImage image(QSize(600, 400), QImage::Format_RGB32);
if (pixmap) {
image = pixmap->toImage();
} else {
image.fill(Qt::gray);
}
QPainter painter(&image);
auto pen = painter.pen();
pen.setColor(Qt::red);
pen.setWidth(5);
painter.setPen(pen);
painter.drawPoint(x, y);
ui->imageLabel->setPixmap(QPixmap::fromImage(image));
ui->textLabel->setText(ui->textLabel->text().append("\nP(%1,%2)").arg(QString::number(x), QString::number(y)));
});
}
MainWindow::~MainWindow()
{
delete ui;
}
mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>521</width>
<height>450</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="imageLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="textLabel">
<property name="text">
<string>Points:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>y:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="yLineEdit"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="xLineEdit"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>x:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="drawButton">
<property name="text">
<string>Draw</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>521</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
Best regards
I have a big doubt and problem. After try a lot of tutorials and examples, I cannot receive signal clicks in my QLabel. If I do the same, but in a QDialog (not in a QLabel), I can know the status of the mouse.
I paste my example code, before that, I present my steps to make the project:
I make a project, make a QMainWindow (named testWindow, maked graphically), after that, I add a QLabel (lblMouse), I mark the mouseTracking property as true. After execute, my QLabel lblMouse doesn't react to my mouse events.
Another doubt is: after execute my program, the text of my QLabel is not "Hello" as I assign in his constructor, it will be executed after ui is executed? I can change it from the constructor of the ui with ui->lblMouse->setText("Hello"); (Probably I have an error, I'm a C programmer and I'm trying to enter in the C++ world)
After that, I edit the code (testWindow.cpp and testWindow.h):
Here is my cpp code:
testWindow::testWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::testWindow)
{
ui->setupUi(this);
//It will not be neccesary because I mark on the checkbox of mouseTracking
ui->lblMouse->setMouseTracking(true);
connect(ui->lblMouse, SIGNAL(Mouse_Pos()), this, SLOT(Mouse_current_pos()));
connect(ui->lblMouse, SIGNAL(Mouse_Pressed()), this, SLOT(Mouse_Pressed()));
connect(ui->lblMouse, SIGNAL(Mouse_Left()), this, SLOT(Mouse_left()));
}
testWindow::~testWindow()
{
delete ui;
}
void testWindow::Mouse_current_pos()
{
ui->lblMouse_Current_Pos->setText(QString("X = aa, Y = aa")/*.arg(ui->lblMouse->x())*/);
}
void testWindow::Mouse_Pressed()
{
ui->lblMouse_Current_Pos->setText(QString("X = aa, Y = aa")/*.arg(ui->lblMouse->x())*/);
}
void testWindow::Mouse_left()
{
ui->lblMouse_Current_Pos->setText(QString("X = aa, Y = aa")/*.arg(ui->lblMouse->x())*/);
}
lblMouse::lblMouse(QWidget *parent): QLabel(parent)
{
// strange for me, the initial text of the label is not Hello
this->setText("Hello");
}
lblMouse::~lblMouse()
{
}
void lblMouse::mouseMoveEvent(QMouseEvent *ev)
{
this->xpos = ev->x();
this->ypos = ev->y();
emit Mouse_Pos();
}
void lblMouse::mousePressEvent(QMouseEvent *)
{
emit Mouse_Pressed();
// ev->x();
}
void lblMouse::leaveEvent(QEvent *)
{
emit Mouse_Left();
}
Here is my h file:
#ifndef TESTWINDOW_H
#define TESTWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QMouseEvent>
#include <QEvent>
#include <QDebug>
namespace Ui {
class testWindow;
class lblMouse;
}
class lblMouse : public QLabel
{
Q_OBJECT
public:
explicit lblMouse(QWidget *parent = 0);
~lblMouse();
int xpos,ypos;
void leaveEvent(QEvent *);
protected:
void mouseMoveEvent(QMouseEvent *ev);
void mousePressEvent(QMouseEvent *ev);
signals:
void Mouse_Pressed();
void Mouse_Pos();
void Mouse_Left();
};
class testWindow : public QMainWindow
{
Q_OBJECT
public:
explicit testWindow(QWidget *parent = 0);
~testWindow();
private:
Ui::testWindow *ui;
private slots:
void Mouse_current_pos();
void Mouse_Pressed();
void Mouse_left();
};
#endif // TESTWINDOW_H
Also, here is my .ui file (thanks #Thomas ):
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>testWindow</class>
<widget class="QMainWindow" name="testWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="lblMouse">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>331</width>
<height>241</height>
</rect>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="text">
<string>Mouse Area</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>400</x>
<y>50</y>
<width>201</width>
<height>191</height>
</rect>
</property>
<property name="title">
<string>Mouse Events</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lblMouse_Current_Pos">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="text">
<string>x=0, Y=0</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblMouse_Current_Event">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>23</height>
</rect>
</property>
<widget class="QMenu" name="menuMenu">
<property name="title">
<string>&Menu</string>
</property>
<addaction name="actionImportar"/>
</widget>
<addaction name="menuMenu"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionImportar">
<property name="text">
<string>&Importar...</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
Edit:
I'm seing a runtime error in the console (is not a compilation error, I got this messages after run the program, but it continues running):
QObject::connect: No such signal QLabel::Mouse_Left() in
../testwindow.cpp:17
QObject::connect: (sender name: 'lblMouse')
QObject::connect: (receiver name: 'testWindow')
PD: I'm not sure if it is the problem. I have tested other ways to do this and I have not good results.
Thanks!
Your label in ui is QLabel class, but you have created lblMouse. So, in ui you must change code
<widget class="QLabel" name="lblMouse">
to
<widget class="lblMouse" name="lblMouse">
EDIT:
To change this you can:
Use any text editor;
Go to Designer in Qt Creator chosing your ui, select your QLabel, call context menu and click "Promote to...". Then check that "Base class name" is correct (QLabel), write your class (lblMouse) in "Promoted class name" field, click "Add" button, then "Promote" button. That's all. Your label now your own label class.
About setText() method.
Go to designer;
Choose your label;
In right side in object propeties find QLabel area and click on a round arrow front of "text" property. That's all. Now, if you do setText() method in constructor - it will works.
You just need to use your lblMouse class.
In .h file, add this in class testWindow
lblMouse *lblMouse_Current_Pos;
In .cpp file, add this in contructor:
lblMouse_Current_Pos = new lblMouse(this);
lblMouse_Current_Pos->setMouseTracking(true);
connect(lblMouse_Current_Pos, SIGNAL(Mouse_Pos()), this, SLOT(Mouse_current_pos()));
connect(lblMouse_Current_Pos, SIGNAL(Mouse_Pressed()), this, SLOT(Mouse_Pressed()));
connect(lblMouse_Current_Pos, SIGNAL(Mouse_Left()), this, SLOT(Mouse_left()));
I am trying to render an image at the appropriate size inside a QVBoxLayout, but I am unable to retrieve the correct size. The layout contains a QLabel, which is displayed at a good size within the designer view (see image). The goal is to display an image at the maximal available size.
Here are my attempts to get the size (all failed):
VideoResourceWidget::VideoResourceWidget(VideoResource* resource, QWidget *parent) :
QWidget(parent),
ui(new Ui::VideoResourceForm),
m_videoResource(resource)
{
ui->setupUi(this);
// INFO: -> size = (670,463) // this seems to be too small
m_videoSize = this->geometry().size();
// first attempt -> size = (0,0)
m_videoSize = this->geometry().size();
m_videoSize.setHeight(m_videoSize.height() - ui->controllerLayout->geometry().height());
// second attempt -> size = (100,30) way too small
m_videoSize = ui->videoLayout->itemAt(ui->videoLayout->indexOf(ui->frameLabel))->geometry().size();
ui->videoLayout->activate(); // hint from another question
// forth attempt -> size = (145,428) better but not still too small
m_videoSize = ui->videoLayout->itemAt(ui->videoLayout->indexOf(ui->frameLabel))->geometry().size();
// third attempt -> size = (670,434) there is still a lot more room
m_videoSize = this->geometry().size();
m_videoSize.setHeight(m_videoSize.height() - ui->controllerLayout->geometry().height());
ui->videoLayout->setSpacing(1);
ui->frameLabel->setMargin(0);
ui->videoLayout->activate(); // hint from another question
// fifth attempt -> size = (145,428) same as before
m_videoSize = ui->videoLayout->itemAt(ui->videoLayout->indexOf(ui->frameLabel))->geometry().size();
// sixth attempt -> size = (670,434) same as before
m_videoSize = this->geometry().size();
m_videoSize.setHeight(m_videoSize.height() - ui->controllerLayout->geometry().height());
QImage frame = m_videoResource->firstFrame();
ui->frameLabel->setPixmap(QPixmap::fromImage(frame).scaled(m_videoSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
connect(ui->nextFrameButton, SIGNAL(clicked()), this, SLOT(nextFrame()));
}
This is the GUI after displaying the VideoResourceWidget for the first time.
While the end result does not have to be pretty, I would love to use the available space effectively.
Update: I updated the screen shots to reflect my latest attempts.
Update: minimal example:
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>771</width>
<height>580</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
<item>
<layout class="QHBoxLayout" name="displayLayout" stretch="0,0,0">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="frameLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="controllerLayout" stretch="1,0">
<item>
<widget class="QScrollBar" name="horizontalScrollBar">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="nextButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>771</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void next();
private:
Ui::MainWindow *ui;
QSize m_imageSize;
QImage m_image;
};
#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);
this->layout()->activate();
connect(ui->nextButton, SIGNAL(clicked()), this, SLOT(next()));
// Goal: display the image centered using the maximally available space
m_image = QImage("/tmp/lena.jpg");
m_imageSize = ui->frameLabel->size();
ui->frameLabel->setPixmap(QPixmap::fromImage(m_image).scaled(m_imageSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::next()
{
// just redraw
m_imageSize = ui->frameLabel->size();
ui->frameLabel->setPixmap(QPixmap::fromImage(m_image).scaled(m_imageSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
Decrease the size of the margins and spacing (play with it. I am not sure which is what) of your layouts. This way the label gets more space, and so does your picture.
I am not sure what you expect it to look like, but the second screen shot looks very good to me. (keep aspect ration makes it take the height of the label). It's just not centered.
spacing
margin
I'd try to remove the spacers, first. Then set the Label's sizeHint (as somebody else already pointed out).
If you really need the spacers in Place, set their stretchFactors to "0", and the stretchFactor of the Label to "1".
Actually I wouldn't use a QLabel to render a video, but I guess this is just a test, and I know QLabel is easy to use for displaying pixmaps. My choice would be to go for performance and reimplement QGLWidget and do the video-render via OpenGL.