My program should:
collect some input from QLineEdits;
convert it into QStrings;
add it to some QStrings which are constant;
output the whole stuff in a QTextEdit when a button is clicked.
Below is the simplified model of the program. It can be compiled; I get no errors; however, it doesn't do what I need. It just fails to output and I have really no idea why. I've struggled too hard to get it show no errors and now I've run out of ideas. Can anybody help me please?
#include <QtGui>
#include <QtCore>
class MyObject : public QObject
{
Q_OBJECT
public:
QTextEdit text;
QString c;
public slots:
void onClicked() {
text.setText(c);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget mw;
mw.setWindowTitle("Main Window");
mw.resize(400, 400);
mw.show();
QLabel label ("Enter something:", &mw);
label.setAlignment(Qt::AlignHCenter);
label.show();
QLineEdit line (&mw);
line.show();
QString a = line.text();
QString b = "This line is to be added";
QString c = a+b;
QTextEdit text (&mw);
text.show();
QPushButton btn ("Convert", &mw);
MyObject obj;
QObject::connect(
&btn,
SIGNAL(clicked()),
&obj,
SLOT(onClicked()));
btn.show();
QVBoxLayout layout_mw;
layout_mw.addWidget(&label);
layout_mw.addWidget(&line);
layout_mw.addWidget(&btn);
layout_mw.addWidget(&text);
mw.setLayout(&layout_mw);
return app.exec();
}
#include "sample.moc"
According to the code you provide it seems that you do not know that:
Qt works asynchronously, for example the value of a that you get is before the window is displayed, what value will it have? Well, it will have an empty string, so at what moment should I ask for the text? right in the slot that is called when the button is pressed.
Variables with the same name do not imply that they are the same, for example you have 2 QTextEdit with the name of text, these are different objects.
So as you realize the objects (widgets) must have the same scope to be able to interact with each other, so I will create a class that inherits from QWidget and that has the other elements as attributes.
#include <QtGui>
#include <QtCore>
class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent=nullptr):
QWidget(parent)
{
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(&label);
layout->addWidget(&line);
layout->addWidget(&button);
layout->addWidget(&textedit);
label.setText("Enter something:");
label.setAlignment(Qt::AlignHCenter);
button.setText("Convert");
connect(&button, SIGNAL(clicked()), this, SLOT(onClicked()));
}
private slots:
void onClicked(){
QString a = line.text();
QString b = "This line is to be added";
QString c = a+b;
textedit.setText(c); // or textedit.append(c);
}
private:
QLabel label;
QLineEdit line;
QPushButton button;
QTextEdit textedit;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Widget w;
w.show();
return app.exec();
}
#include "sample.moc"
Related
I am doing a qt project, my goal is to draw something based on my input. The signal is in the main, and the drawing is in another object, I am not able to connect them.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Frequency fre; //this is the class that does the drawing
QWidget *window = new QWidget;
QGridLayout *grid = new QGridLayout;
QGroupBox *groupBox = new QGroupBox(QObject::tr("Volume"));
QSpinBox *spinBox = new QSpinBox;
spinBox->setRange(0, 5);
QObject::connect(spinBox, SIGNAL(valueChanged(int)),&fre, SLOT(setVolume(int)));
QVBoxLayout *Vbox = new QVBoxLayout;
Vbox->addWidget(spinBox);
groupBox->setLayout(Vbox);
grid->addWidget(groupBox, 4,7,1,1);
window->setLayout(grid);
window->show();
return app.exec();
}
This is how I set up the Frequency class :
in h file
class Frequency : public QGLWidget
{
Q_OBJECT
public slots:
void setVolume(int value);
in cpp file
void Frequency :: setVolume(int val) {
vol = val;
updateGL();
}
void Frequency :: paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw();
}
Since I can't put all this in the comment section, I'm going to put it here:
I copied your code and I'm not able to reproduce the error with Qt version 5.14.0, because when I change the value in any way, the method, void MyObject::setVolume(int value) is being called.
This code should work for you. Possibly, you are running it in release mode, and used a breakpoint to check if it was called (which doesn't always work on release mode).
// #include "QtWidgetsApplication4.h"
#include <QtWidgets/QApplication>
#include "MyObject.h"
#include <QGridLayout>
#include <QGroupBox>
#include <QSpinBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// QtWidgetsApplication4 w;
// w.show();
// return a.exec();
MyObject object;
QWidget* window = new QWidget;
QGridLayout* grid = new QGridLayout;
QGroupBox* groupBox = new QGroupBox(QObject::tr("Volume"));
QSpinBox* spinBox = new QSpinBox;
spinBox->setRange(0, 5);
QObject::connect(spinBox, SIGNAL(valueChanged(int)), &object, SLOT(setVolume(int)));
QVBoxLayout* Vbox = new QVBoxLayout;
Vbox->addWidget(spinBox);
groupBox->setLayout(Vbox);
grid->addWidget(groupBox, 4, 7, 1, 1);
window->setLayout(grid);
window->show();
return a.exec();
}
#pragma once
#include <QObject>
class MyObject : public QObject
{
Q_OBJECT
public slots:
void setVolume(int value);
private:
int m_volume;
};
#include "MyObject.h"
void MyObject::setVolume(int value)
{
m_volume = value;
}
I have a QQuickwidget in a Qt C++ application where i have loaded a QML file (main.qml) and using QAction(actionstart) and C++ functions i have to load another QML file(main1.qml) slightly different to previous one on the same QQuickWidget object.
I am able to do this , but my 2nd QML file is overlapped from the middle section of QQuickwidget and further.
I have did this to stop overlapping of 2 QML files but not successful completely. count3 = 1 is defined in public section of Guiapplication.h file.
void GuiApplication::on_actionstart_triggered()
{
if (count3 == 1)
{
set_animation();
count3 = 2;
}
}
C++ Function for loading 1st QML file(main.qml)
void GuiApplication::rolling_animation()
{
QQuickView *quickWidget=new QQuickView();
QWidget *contain = QWidget::createWindowContainer(quickWidget,this);
contain->setMinimumSize(1008,349);
contain->setMaximumSize(1008,349);
contain->setFocusPolicy(Qt::TabFocus);
quickWidget->setSource(QUrl("qrc:/Resources/main.qml"));
ui->horizontalLayout_6->addWidget(contain);
}
C++ Function for loading 2nd QML file(main1.qml)
void GuiApplication::set_animation()
{
QQuickView *quickWidget=new QQuickView();
QWidget *Contain = QWidget::createWindowContainer(quickWidget,this);
Contain->setMinimumSize(1008,349);
Contain->setMaximumSize(1008,349);
Contain->setFocusPolicy(Qt::TabFocus);
quickWidget->setSource(QUrl("qrc:/Resources/main1.qml"));
ui->horizontalLayout_6->addWidget(Contain);
//ui->horizontalLayout_9->invalidate();
//ui->horizontalLayout_9->removeWidget(quickWidget_4);
}
output window image
Depending on whether you want to save or not the state of the QML that you want to hide there are the following alternatives:
Reject the same QQuickWidget (I recommend changing QQuickView to QQuickWidget) and just change the source.
#include <QtQuickWidgets>
class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent=nullptr):
QWidget(parent),
m_widget(new QQuickWidget)
{
m_widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
QPushButton *button1 = new QPushButton("show 1");
QPushButton *button2 = new QPushButton("show 2");
QHBoxLayout *lay = new QHBoxLayout(this);
QVBoxLayout *vlay = new QVBoxLayout;
vlay->addWidget(button1);
vlay->addWidget(button2);
lay->addLayout(vlay);
lay->addWidget(m_widget);
connect(button1, &QPushButton::clicked, this, &Widget::show1);
connect(button2, &QPushButton::clicked, this, &Widget::show2);
show1();
}
private slots:
void show1(){
m_widget->setSource(QUrl("qrc:/main1.qml"));
}
void show2(){
m_widget->setSource(QUrl("qrc:/main2.qml"));
}
private:
QQuickWidget *m_widget;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
Use 2 QuickWidgets and use a QStackedWidget to toggle the widgets, with this method only hidden so the state of the QML will persist, in the previous case when changing the source is lost.
#include <QtQuickWidgets>
class Widget: public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent=nullptr):
QWidget(parent),
m_stacked_widget(new QStackedWidget)
{
for(const QString & url: {"qrc:/main1.qml", "qrc:/main2.qml"}){
QQuickWidget *widget = new QQuickWidget;
widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget->setSource(QUrl(url));
m_stacked_widget->addWidget(widget);
}
QPushButton *button1 = new QPushButton("show 1");
QPushButton *button2 = new QPushButton("show 2");
QHBoxLayout *lay = new QHBoxLayout(this);
QVBoxLayout *vlay = new QVBoxLayout;
vlay->addWidget(button1);
vlay->addWidget(button2);
lay->addLayout(vlay);
lay->addWidget(m_stacked_widget);
connect(button1, &QPushButton::clicked, this, &Widget::show1);
connect(button2, &QPushButton::clicked, this, &Widget::show2);
show1();
}
private slots:
void show1(){
m_stacked_widget->setCurrentIndex(0);
}
void show2(){
m_stacked_widget->setCurrentIndex(1);
}
private:
QStackedWidget *m_stacked_widget;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
The examples can be found here
What is the procedure to make a text being written in a QLineEdit widget, dynamically display inside a QTextEdit that already contains some text?
For example, let us say that a QLineEdit asks for a name where one writes "John". Is it possible to display it in real time inside a QTextEdit containing :
The name is + textFromQLineEdit + , age 24 ?
The displayed text has to dynamically take into account the changes being made to the QLineEdit so that the user does not need to press a button or press enter to see his/her name appear.
The following is the minimal code for connecting the two widgets to each other using the signal textChanged() from QLineEdit and the slot setText() from QTextEdit (which does not allow for adding some text before and after the text from the QLineEdit) :
#include <QLineEdit>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QTextEdit>
#include <QApplication>
class SmallWindow : public QWidget
{
Q_OBJECT
public:
SmallWindow();
private:
QLineEdit *nameLine;
QTextEdit *textBox;
};
SmallWindow::SmallWindow() : QWidget()
{
setFixedSize(300,250);
QLineEdit *nameLine = new QLineEdit;
QTextEdit *textBox = new QTextEdit;
QWidget::connect(nameLine,SIGNAL(textChanged(QString)),textBox,SLOT(setText(QString)));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(nameLine);
layout->addWidget(textBox);
QGroupBox *group = new QGroupBox(this);
group->setLayout(layout);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
SmallWindow window;
window.show();
app.exec();
}
#include "main.moc"
What should be done to keep the text before and after the QLineEdit text in place and updating the QTextEdit box in real time?
Create special slot:
void SmallWindow::pasteText(const QString& str)
{
textBox->setText(QString("The name is %1 , age 24").arg(str));
}
and don't use textChanged() signal because you need only one name accepted by user, so you need QLineEdit::editingFinished() (or maybe QLineEdit::returnPressed(), it depends on your needs)
connect(nameLine,SIGNAL(editingFinished(QString)),this,SLOT(pasteText(QString)));
Also you don't need QWidget::connect, because you write this code inside QObject subclass, so it is not necessary.
Also these lines:
QLineEdit *nameLine = new QLineEdit;
QTextEdit *textBox = new QTextEdit;
should be:
nameLine = new QLineEdit;
textBox = new QTextEdit;
Create an own slot for the text update. I think that you have also some errors in your code.
Widgets nameLine and textBox are already defined in the SmallWindow.h. You probably want to create them in SmallWindow.cpp following way:
nameLine = new QLineEdit;
textBox = new QTextEdit;
Also GroupBox group is not set to any layouts. Perhaps you want to create one layout more and set the widget there?
QVBoxLayout *mainlayout = new QVBoxLayout;
mainlayout->addWidget(group);
this->setLayout(mainlayout);
If you create an own slot for the text update, you can just change text content of the textBox there:
SmallWindow.h
#ifndef SMALLWINDOW_H
#define SMALLWINDOW_H
#include <QLineEdit>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QTextEdit>
class SmallWindow : public QWidget
{
Q_OBJECT
public:
SmallWindow();
private slots:
void updateLineEditText(QString name);
private:
QLineEdit *nameLine;
QTextEdit *textBox;
};
#endif // SMALLWINDOW_H
SmallWindow.cpp
#include "SmallWindow.h"
SmallWindow::SmallWindow() : QWidget()
{
setFixedSize(300,250);
nameLine = new QLineEdit;
textBox = new QTextEdit;
connect(nameLine,SIGNAL(textChanged(QString)),this,
SLOT(updateLineEditText(QString)));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(nameLine);
layout->addWidget(textBox);
QGroupBox *group = new QGroupBox(this);
group->setLayout(layout);
QVBoxLayout *mainlayout = new QVBoxLayout;
mainlayout->addWidget(group);
this->setLayout(mainlayout);
}
void SmallWindow::updateLineEditText(QString name) {
QString textEditString("The name is ");
textEditString.append(name);
textEditString.append(", age 24 ?");
textBox->setText(textEditString);
}
This is a minimal example in Qt 5, using C++11. It is about as concise as it would be in Python. If you are using Qt 5, then your question should have looked exactly as it does below, save for the connect statement. This is what "minimal" means when it comes to Qt. Avoid the fluff and boilerplate that doesn't add to the problem. There's no need to have a separate class for the window in such a simple example.
#include <QVBoxLayout>
#include <QLineEdit>
#include <QTextEdit>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
QVBoxLayout layout(&window);
QLineEdit name;
QTextEdit text;
layout.addWidget(&name);
layout.addWidget(&text);
QObject::connect(&name, &QLineEdit::textChanged, [&](const QString & name){
text.setPlainText(QString("The name is %1, age 24.").arg(name));
});
window.show();
return app.exec();
}
The same in Qt 4 is below - note the absence of any manual memory management. That's how your question ideally should have looked for Qt 4, without the slot's implementation of course. You can use the connectSlotsByName or an explicit connect, of course - that's just a matter of style.
#include <QVBoxLayout>
#include <QLineEdit>
#include <QTextEdit>
#include <QApplication>
class Window : public QWidget {
Q_OBJECT
QVBoxLayout m_layout; // not a pointer!
QLineEdit m_name; // not a pointer, must come after the layout!
QTextEdit m_text;
Q_SLOT void on_name_textChanged(const QString & name) {
m_text.setPlainText(QString("The name is %1, age 24.").arg(name));
}
public:
Window() : m_layout(this) {
m_layout.addWidget(&m_name);
m_layout.addWidget(&m_text);
m_name.setObjectName("name");
QMetaObject::connectSlotsByName(this);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window window;
window.show();
return app.exec();
}
#include "main.moc"
I have a custom widget with some standard child widgets inside. If I make a separate test project and redefine my custom widget to inherit QMainWindow, everything is fine. However, if my custom widget inherits QWidget, the window opens, but there are no child widgets inside.
This is the code:
controls.h:
#include <QtGui>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
class Controls : public QWidget
{
Q_OBJECT
public:
Controls();
private slots:
void render();
private:
QWidget *frame;
QWidget *renderFrame;
QVBoxLayout *layout;
QLineEdit *rayleigh;
QLineEdit *mie;
QLineEdit *angle;
QPushButton *renderButton;
};
controls.cpp:
#include "controls.h"
Controls::Controls()
{
frame = new QWidget;
layout = new QVBoxLayout(frame);
rayleigh = new QLineEdit;
mie = new QLineEdit;
angle = new QLineEdit;
renderButton = new QPushButton(tr("Render"));
layout->addWidget(rayleigh);
layout->addWidget(mie);
layout->addWidget(angle);
layout->addWidget(renderButton);
frame->setLayout(layout);
setFixedSize(200, 400);
connect(renderButton, SIGNAL(clicked()), this, SLOT(render()));
}
main.cpp:
#include <QApplication>
#include "controls.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Controls *controls = new Controls();
controls->show();
return app.exec();
}
This opens up a window with correct dimensions, but with no content inside.
Bear in mind this is my first day using Qt. I need to make this work without inheriting QMainWindow because later on I need to put this on a QMainWindow.
You're missing a top level layout:
Controls::Controls()
{
... (yoour code)
QVBoxLayout* topLevel = new QVBoxLayout(this);
topLevel->addWidget( frame );
}
Or, if frame is not used anywhere else, directly:
Controls::Controls()
{
layout = new QVBoxLayout(this);
rayleigh = new QLineEdit;
mie = new QLineEdit;
angle = new QLineEdit;
renderButton = new QPushButton(tr("Render"));
layout->addWidget(rayleigh);
layout->addWidget(mie);
layout->addWidget(angle);
layout->addWidget(renderButton);
setFixedSize(200, 400);
connect(renderButton, SIGNAL(clicked()), this, SLOT(render()));
}
Note that setLayout is done automatically when QLayout is created (using parent widget)
You'll want to set a layout on your Controls class for managing its child sizes. I'd recommend removing your frame widget.
controls.cpp
Controls::Controls()
{
layout = new QVBoxLayout(this);
.
.
.
}
main.cpp
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
Greetings all,
Is there any widget to separate two QWidgets and also give full focus to a one widget.
As shown in following figure ?
Thanks in advance,
umanga
How about QSplitter?
QWidget 1, for exmaple, QListView. QWidget 2 is a combination of QWidgets (the left part is simple QPushButton with show/hide caption, and the right part another widget)... All you have to do, is to hide your QWidget2 when user clicked on QPushButton...
If you need an example, I may post it.
Updated
main.cpp
#include "splitter.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
splitter w;
w.show();
return a.exec();
}
splitter.h
#ifndef SPLITTER_H
#define SPLITTER_H
#include <QtGui/QDialog>
class splitter : public QDialog
{
Q_OBJECT;
QWidget* widget1;
QWidget* widget2;
QPushButton* button;
public:
splitter(QWidget *parent = 0, Qt::WFlags flags = 0);
~splitter();
private slots:
void showHide(void);
};
#endif // SPLITTER_H
splitter.cpp
#include <QtGui>
#include "splitter.h"
splitter::splitter(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
QApplication::setStyle("plastique");
QListView* listView = new QListView;
QTableView* tableView = new QTableView;
button = new QPushButton("Hide >");
widget1 = new QWidget;
QHBoxLayout* w1Layout = new QHBoxLayout;
w1Layout->addWidget(listView);
w1Layout->addWidget(button);
widget1->setLayout(w1Layout);
widget2 = new QWidget;
QHBoxLayout* w2Layout = new QHBoxLayout;
w2Layout->addWidget(tableView);
widget2->setLayout(w2Layout);
QSplitter *mainSplitter = new QSplitter(this);
mainSplitter->addWidget(widget1);
mainSplitter->addWidget(widget2);
connect(button, SIGNAL(clicked()), this, SLOT(showHide()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(mainSplitter);
setLayout(mainLayout);
}
splitter::~splitter()
{}
void splitter::showHide(void)
{
if (widget2->isVisible())
{ // hide
widget2->setVisible(false);
button->setText("< Show");
}
else
{ // show
widget2->setVisible(true);
button->setText("Hide >");
}
}