How do I fully clear a QTreeWidget selection? - c++

I'm trying to make a program that has multiple QTreeWidget's. However, my goal is to ONLY allow for 1 QTreeWidget row to be selected at a time.
I've kind of managed to make this happen using the currentItemChanged signal, but it bugs out.
To reproduce the issue...
Select a row on one QTreeWidget.
Select another row on the OTHER QTreeWidget. At this point all QTreeWidget selection are removed (great that's exactly what I wanted).
Select the same row on the same QTreeWidget as step 1. At this point it has now bugged out because your previous selection is still chosen...
Am I clearing the selection improperly, and if so how should I be clearing it?
Here's a picture of the issue.
Here is my source...
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTreeWidget>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void OnSelectedTreeValueChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QTreeWidget>
#include <QTreeWidgetItem>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->treeWidget->expandAll();
ui->treeWidget->setItemsExpandable(false);
ui->treeWidget_2->expandAll();
ui->treeWidget_2->setItemsExpandable(false);
connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(OnSelectedTreeValueChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
connect(ui->treeWidget_2, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(OnSelectedTreeValueChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::OnSelectedTreeValueChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
if(current->childCount() == 0)
{
// Get OUR parrent item.
QTreeWidgetItem* parent_item = current->parent();
// Go through each tree & deselect selections.
QObject* sender_object = sender();
QTreeView* sender_tree = static_cast<QTreeView*>(sender_object);
const QList<QTreeWidget*> children = ui->TreeScrollAreaContents->findChildren<QTreeWidget*>(QRegularExpression(), Qt::FindDirectChildrenOnly);
for(QList<QTreeWidget*>::const_iterator it = children.begin(); it != children.end(); it++)
{
QTreeWidget* child_tree = *it;
if(sender_tree != child_tree)
{
child_tree->clearSelection();
child_tree->clearFocus();
}
}
}
}
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>400</width>
<height>176</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QScrollArea" name="TreeScrollArea">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>401</width>
<height>171</height>
</rect>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="TreeScrollAreaContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>169</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">#TreeScrollAreaContents {
background-color: #000000;
}</string>
</property>
<layout class="QGridLayout" name="TreeScrollAreaGridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QTreeWidget" name="treeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<column>
<property name="text">
<string>1</string>
</property>
</column>
<item>
<property name="text">
<string>Item 1</string>
</property>
<item>
<property name="text">
<string>Sub Item 1</string>
</property>
</item>
<item>
<property name="text">
<string>Sub Item 2</string>
</property>
</item>
<item>
<property name="text">
<string>Sub Item 3</string>
</property>
</item>
<item>
<property name="text">
<string>Sub Item 4</string>
</property>
</item>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QTreeWidget" name="treeWidget_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<column>
<property name="text">
<string>1</string>
</property>
</column>
<item>
<property name="text">
<string>Item 1</string>
</property>
<item>
<property name="text">
<string>Sub Item 1</string>
</property>
</item>
<item>
<property name="text">
<string>Sub Item 2</string>
</property>
</item>
<item>
<property name="text">
<string>Sub Item 3</string>
</property>
</item>
<item>
<property name="text">
<string>Sub Item 4</string>
</property>
</item>
</item>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

One thing is the currentItem and another is the selected items, instead of using the currentItemChanged signal you must use the signal itemSelectionChanged. When using clearSelection() the respective QTreeWidget will also emit the signal itemSelectionChanged and this could generate an infinite loop, the solution is to use blockSignals().
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTreeWidgetItem>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
private slots:
void OnSelectedTreeValueChanged(); // remove arguments
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTreeWidget>
#include <QTreeWidgetItem>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
const QList<QTreeWidget*> childrens = ui->TreeScrollAreaContents->findChildren<QTreeWidget*>(QRegularExpression(), Qt::FindDirectChildrenOnly);
for(QTreeWidget* child_tree: childrens)
{
child_tree->expandAll();
child_tree->setItemsExpandable(false);
connect(child_tree, &QTreeWidget::itemSelectionChanged, this, &MainWindow::OnSelectedTreeValueChanged);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::OnSelectedTreeValueChanged()
{
QTreeWidget *sender_tree = qobject_cast<QTreeWidget *>(sender());
if(sender_tree->currentItem()->childCount() == 0)
{
const QList<QTreeWidget*> childrens = ui->TreeScrollAreaContents->findChildren<QTreeWidget*>(QRegularExpression(), Qt::FindDirectChildrenOnly);
for(QTreeWidget* child_tree: childrens)
{
if(sender_tree != child_tree)
{
child_tree->blockSignals(true);
child_tree->clearSelection();
child_tree->blockSignals(false);
}
}
}
}
Note:
I will explain why your method does not work, you are using the currentItem as a basic element of your algorithm, but a currentItem may be selected or no, clearSelection does not affect the currentItem.

Related

How to add a "new tab" on an existing QTabWidget using a QPushButton

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.

How to update a window in QT?

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);

Can not draw or change pixels' color on QImage

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

How to add "member" to MainWindow class in Qt

So i have started to learn Qt, and i got hold of Qt5 C++ GUI Programming Cookbook. I wanted to make a simple video converter, and there is a example on how to do it in the book.
But executing the code from the book gives me an error:
'Ui::MainWindow' has no member named 'filePath'
ui->filePath->setText(fileName);
^
So i guess i have to add filePath to the MainWindow, but since im new to Qt and C++ i dont know exactly how to do that.
Here is mainwindow.h
#include <QMainWindow>
#include <QFileDialog>
#include <QProcess>
#include <QMessageBox>
#include <QScrollBar>
#include <QDebug>
#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();
QProcess* process;
QString outputText;
QString fileName;
QString outputFileName;
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void processStarted();
void readyReadStandardOutput();
void processFinished();
private:
Ui::MainWindow *ui;
};
#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);
process = new QProcess(this);
connect(process, SIGNAL(started()), this,
SLOT(processStarted()));
connect(process,SIGNAL(readyReadStandardOutput()),
this,SLOT(readyReadStandardOutput()));
connect(process, SIGNAL(finished(int)), this,
SLOT(processFinished()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, "OpenVideo", "", "Video Files (*.avi *.mp4 *.mov)");
ui->filePath->setText(fileName);
}
void MainWindow::on_pushButton_2_clicked()
{
QString ffmpeg = "C:/FFmpeg/bin/ffmpeg";
QStringList arguments;
fileName = ui->filePath->text();
if (fileName != "")
{
QFileInfo fileInfo = QFile(fileName);
outputFileName = fileInfo.patch() + "/" + fileInfo.completeBaseName();
if (QFile::exists(fileName))
{
//0-AVI
//1-MP4
//2-MOV
int format = ui -> fileFormat-> currentIndex();
if (format ==0)
{
outputFileName += ".avi";
}
else if (format ==1)
{
outputFileName += ".mp4";
}
else if (format ==2)
{
outputFileName += ".mov";
}
qDebug()<<outputFileName<<format;
arguments<< "-i"<<fileName<<outputFileName;
qDebug()<<arguments;
process->setProcessChannelMode(QProcess::MergedChannels);
process->start(ffmpeg,arguments);
}
else
{
QMessageBox::warning(this,"Failed", "Failed to open video file.");
}
else
{
QMessageBox::warning(this,"Failed", "Failed to open video file.");
}
}
}
void MainWindow::processStarted()
{
qDebug() << "Process started.";
ui->browseButton->setEnabled(false);
ui->fileFormat->setEditable(false);
ui->convertButton->setEnabled(false);
}
void MainWindow::readyReadStandardOutput()
{
outputText += process->readAllStandardOutput();
ui->outputDisplay->setText(outputText);
ui->outputDisplay->verticalScrollBar()->setSliderPosition(ui->outputDisplay->verticalScrollBar()->maximum());
}
void MainWindow::processFinished()
{
qDebug() << "Process finished.";
if (QFile::exists(outputFileName))
{
QMessageBox::information(this, "Success", "Videosuccessfully converted.");
}
else
{
QMessageBox::information(this, "Failed", "Failed to convertvideo.");
}
ui->browseButton->setEnabled(true);
ui->fileFormat->setEditable(true);
And 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>404</width>
<height>334</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>281</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Browse</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>371</width>
<height>22</height>
</rect>
</property>
<item>
<property name="text">
<string>AVI</string>
</property>
</item>
<item>
<property name="text">
<string>MP4</string>
</property>
</item>
<item>
<property name="text">
<string>MOV</string>
</property>
</item>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>10</x>
<y>100</y>
<width>371</width>
<height>141</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>10</x>
<y>250</y>
<width>371</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Convert</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>404</width>
<height>21</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 error is in the .ui file. You need to open Designer, click in your filePath, and change its name to filePath. Currently, it is textEdit.
All visual controls that you put on the .ui file via the Designer application should match the names you are using in the C++ code to access them.

Link QLabel to variable (two different classes) in Qt C++

Currently working on getting threading to work with Qt C++ along with using the clearest method to solve the problem. Below is some code to start 3 threads and count to 10000. What i have at the moment is when u press the start and stop buttons the counters do work (using qDebug). However what I want to do is link the counter variable to 3 labels so that when the counter goes up the label for each thread does too (however had no luck with connect as not sure how to link class methods (specifically ui->label->settext to Thread::get_time())).
Currently I am stuck on the final part, as can't find a way to link to label from inside thread.cpp if anyone can help that would be great. As you can imagine gotten a bit lost and not sure where to go from here.
object.h
#ifndef OBJECT_H
#define OBJECT_H
#include <QObject>
#include <QDebug>
#include <QThread>
#include <QApplication>
#include <QMutex>
class Object : public QObject
{
Q_OBJECT
private:
int timealive;
public:
explicit Object(QObject *parent = 0);
void setup(QThread &thread, QObject &object);
void set_time(int number);
int get_time();
bool Stop;
signals:
public slots:
void worker();
};
#endif // OBJECT_H
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void on_pushButton_5_clicked();
void on_pushButton_6_clicked();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
Dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
void Dialog::on_pushButton_clicked()
{
ui->label->setText(QString::number(12));
}
void Dialog::on_pushButton_2_clicked()
{
}
void Dialog::on_pushButton_3_clicked()
{
}
void Dialog::on_pushButton_4_clicked()
{
}
void Dialog::on_pushButton_5_clicked()
{
}
void Dialog::on_pushButton_6_clicked()
{
}
Main.cpp
#include "dialog.h"
#include "object.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog w;
w.show();
QThread thread;
Object thread_object;
thread_object.setup(thread,thread_object);
return a.exec();
}
object.cpp
#include "object.h"
Object::Object(QObject *parent) :
QObject(parent)
{
}
void Object::setup(QThread &thread,QObject &object)
{
object.moveToThread(&thread);
thread.start();
connect(&thread,SIGNAL(started()),this,SLOT(worker()));
}
void Object::worker()
{
for(int i = 0; i < 10000; i++)
{
QMutex mutex;
QMutexLocker locker(&mutex);
this->set_time(i);
qDebug() << i;
if(this->Stop)
{
break;
}
}
}
void Object::set_time(int number)
{
timealive = number;
}
int Object::get_time()
{
return timealive;
}
Dialog.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>286</width>
<height>168</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>261</width>
<height>25</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Number</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>
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_4">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_2">
<property name="geometry">
<rect>
<x>10</x>
<y>70</y>
<width>261</width>
<height>25</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Number</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<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="QPushButton" name="pushButton_5">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_6">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>9</x>
<y>9</y>
<width>261</width>
<height>25</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Number</string>
</property>
</widget>
</item>
<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="QPushButton" name="pushButton">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
Cheers ION
P.s changed code to reflect that I am now using the correct way for threading.