How to get value of an object in another class? Such as I have 2 classes (class WidgetA and class WidgetB) both those classes are created by class Widget, like this:
//widget.h
#include <QWidget>
#include <QtGui>
class widgetA;
class widgetB;
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
private:
QComboBox* comboBox;
QStackedWidget* stackWidget;
widgetA *wa;
widgetB *wb;
};
class widgetA : public QWidget
{
Q_OBJECT
public:
widgetA(QWidget *parent = 0);
private:
QString mystr;
QLineEdit* lineEdit;
};
class widgetB : public QWidget
{
Q_OBJECT
public:
widgetB(QWidget *parent = 0);
QLabel* label;
};
And this is file widget.cpp:
#include "widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
comboBox = new QComboBox(this);
comboBox->addItem(tr("Widget A"));
comboBox->addItem(tr("Widget B"));
wa = new widgetA(this);
wb = new widgetB(this);
stackWidget = new QStackedWidget(this);
stackWidget->addWidget(wa);
stackWidget->addWidget(wb);
stackWidget->setCurrentIndex(0);
connect(comboBox, SIGNAL(currentIndexChanged(int)), stackWidget, SLOT(setCurrentIndex(int)));
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget(comboBox);
layout->addWidget(stackWidget);
setLayout(layout);
}
widgetA::widgetA(QWidget *parent):
QWidget(parent)
{
lineEdit = new QLineEdit;
QHBoxLayout *lay = new QHBoxLayout;
lay->addWidget(lineEdit);
lineEdit->setReadOnly(true);
setLayout(lay);
}
widgetB::widgetB(QWidget *parent):
QWidget(parent)
{
label = new QLabel("Hello QT");
QHBoxLayout* lay = new QHBoxLayout;
lay->addWidget(label);
setLayout(lay);
}
How to I get text of QLabel label in WidgetB class into QString mystr in WidgetA class?
The cleanest way in terms of proper decoupling and separation of concerns is to add a getter forwarding label->text():
QString widgetB::text() const //or more specific name depending on the context
{
return label->text();
}
If you need notification when the value changes, add a signal:
class widgetB : public QWidget {
...
Q_SIGNALS:
void textChanged(const QString& text);
...
};
and emit it whenever you update the label.
Related
I am new in Qt and am using qt creator for the GUI designing, now i have to make a dynamic form in which a label,line edit and a button are added for each feature like length,width,etc.However the features are not static there may be 2 feature sometime and other time there might be 6 depending upon the xml file.thus i want to make a widget which for each feature creates an instance.
I have made basic structure of grouped widget using this:
cal_widget.h
#ifndef CAL_WIDGET_H
#define CAL_WIDGET_H
#include <QWidget>
#include<QVBoxLayout>
#include<QPushButton>
#include<QLineEdit>
class cal_widget : public QWidget
{
Q_OBJECT
public:
explicit cal_widget(QWidget *parent = nullptr);
QVBoxLayout* layout;
QPushButton* btn;
QLineEdit* ln1;
QLineEdit* ln2;
signals:
public slots:
};
#endif // CAL_WIDGET_H
cal_widget.cpp
#include "cal_widget.h"
cal_widget::cal_widget(QWidget *parent) : QWidget(parent)
{
layout = new QVBoxLayout();
btn= new QPushButton();
ln1 = new QLineEdit("mm");
ln2 = new QLineEdit("pix");
layout->addWidget(ln1);
layout->addWidget(btn);
layout->addWidget(ln2);
this->setLayout(layout);
}
and calling the above widget in another form mainwidget.cpp
{
QVBoxLayout* vbox = new QVBoxLayout();
cal_widget* cal1 = new cal_widget(this);
cal_widget* cal2 = new cal_widget(this);
cal_widget* cal3 = new cal_widget(this);
cal_widget* cal4 = new cal_widget(this);
cal_widget* cal5 = new cal_widget(this);
vbox->addWidget(cal1);
vbox->addWidget(cal2);
vbox->addWidget(cal3);
vbox->addWidget(cal4);
vbox->addWidget(cal5);
ui->scrollArea->setLayout(vbox);
}
i am getting result as :this
how can i get desired result
DONE
cal_widget.h
#ifndef CAL_WIDGET_H
#define CAL_WIDGET_H
#include <QWidget>
#include<QGroupBox>
#include<QGridLayout>
#include<QPushButton>
#include<QLineEdit>
class cal_widget : public QGroupBox
{
Q_OBJECT
public:
explicit cal_widget(const QString& feature, QWidget *parent = nullptr);
QGridLayout* layout;
QPushButton* btn;
QLineEdit* ln1;
QLineEdit* ln2;
signals:
public slots:
};
#endif // CAL_WIDGET_H
cal_widget.cpp
#include "cal_widget.h"
cal_widget::cal_widget(const QString& feature, QWidget *parent) : QGroupBox(parent)
{
this->setTitle(feature);
layout = new QGridLayout();
btn= new QPushButton("OK");
ln1 = new QLineEdit("mm");
ln2 = new QLineEdit("pix");
layout->addWidget(ln1,0,0);
layout->addWidget(ln2,0,1);
layout->addWidget(btn,1,0,1,2);
this->setLayout(layout);
}
I would like to change my widget layout from QStackedLayout to QHBoxLayout to QVBoxLayout dynamically by clicking on push buttons. I am able to switch from QVBoxLayout to QHBoxLayout and vice versa, but my approach does not work for QStackedLayout. I've exhausted all options I can think of. A sample code is attached. Does anyone know how I can achieve my objective?
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QStackedLayout>
#include <QGridLayout>
#include <QLabel>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
QPushButton *button1_;
QPushButton *button2_;
QPushButton *button3_;
QHBoxLayout *hLayout_;
QVBoxLayout *vLayout_;
QStackedLayout *sLayout_;
QVBoxLayout *gLayout_;
public slots:
void layoutHorizontal();
void layoutVertical();
void layoutStacked();
private:
bool isStackedLayout_;
QLabel *bar_;
};
#endif // WIDGET_H
#include "widget.h"
#include <QtAlgorithms>
#include <QDebug>
Widget::Widget(QWidget *parent) : QWidget(parent){
bar_ = new QLabel(tr("TEST!"));
button1_ = new QPushButton(tr("to Horizontal Layout"),(bar_));
button2_ = new QPushButton(tr("to Vertical Layout"),(bar_));
button3_ = new QPushButton(tr("to Stacked Layout"),(bar_));
button1_->setStyleSheet("background: rgba(255,255,0,255);");
button2_->setStyleSheet("background: rgba(255,0,255,255);");
button3_->setStyleSheet("background: rgba(0,255,255,255);");
connect(button1_,SIGNAL(clicked()),this,SLOT(layoutHorizontal()));
connect(button2_,SIGNAL(clicked()),this,SLOT(layoutVertical()));
connect(button3_,SIGNAL(clicked()),this,SLOT(layoutStacked()));
gLayout_ = new QVBoxLayout;
setLayout(gLayout_);
hLayout_ = new QHBoxLayout(bar_);
hLayout_->setObjectName(tr("currentLayout"));
gLayout_->addWidget(bar_);
hLayout_->addWidget(button1_);
hLayout_->addWidget(button2_);
hLayout_->addWidget(button3_);
isStackedLayout_ = false;
resize(480,200);
}
Widget::~Widget() { }
void Widget::layoutHorizontal(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QHBoxLayout *hLayout_ = new QHBoxLayout(bar_);
hLayout_->setObjectName(tr("currentLayout"));
hLayout_->addWidget(button1_);
hLayout_->addWidget(button2_);
hLayout_->addWidget(button3_);
isStackedLayout_ = false;
}
void Widget::layoutVertical(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QVBoxLayout *vLayout_ = new QVBoxLayout(bar_);
vLayout_->setObjectName(tr("currentLayout"));
vLayout_->addWidget(button1_);
vLayout_->addWidget(button2_);
vLayout_->addWidget(button3_);
isStackedLayout_ = false;
}
void Widget::layoutStacked(){
QLayout *layout = bar_->findChild<QLayout *>(tr("currentLayout"));
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
delete layout;
QStackedLayout *sLayout_ = new QStackedLayout(bar_);
sLayout_->setObjectName(tr("currentLayout"));
sLayout_->addWidget(button1_);
sLayout_->addWidget(button2_);
sLayout_->addWidget(button3_);
isStackedLayout_ = true;
}
The visibility property on your buttons gets set to "invisible" after pulling widgets out of the QStackedLayout (likely because the QStackedLayout relies on this property to emulate stacking). As such, I was able to get your code to work by adding the following:
void Widget::layoutHorizontal() {
...
button1_->setVisible(true);
button2_->setVisible(true);
button3_->setVisible(true);
isStackedLayout_ = false;
}
It's also worth noting that removing the widgets from the layout prior to deleting it is not necessary. The layout doesn't take ownership of the widgets in it. As such you can delete the following:
layout->removeWidget(button1_);
layout->removeWidget(button2_);
layout->removeWidget(button3_);
Create another widget with only widgets and one layout inside. Then use setLayout for your widget. Sorry for my bad C++ knowledge :)
class ChangeableWidget: public QWidget {
private QVBoxLayout vbox;
private QHBoxLayout hbox;
private QStackedLayout stacked;
private QPushButton button1;
private QPushButton button2;
ChangeableWidget()
{
button1 = new QPushButton("1");
button2 = new QPushButton("2");
vbox = new QVBoxLayout();
vbox.addWidget(button1);
vbox.addWidget(button2);
hbox = new QHBoxLayout();
hbox.addWidget(button1);
hbox.addWidget(button2);
stacked = new QStackedLayout();
stacked.addWidget(button1);
stacked.addWidget(button2);
setLayout(vbox);
}
void ChangeableWidget::layoutVertical()
{
setLayout(vbox);
}
void ChangeableWidget::layoutHorizontal()
{
setLayout(hbox);
}
}
I have ever post a question at there: change text in another class by button But it justs working when second class is create by first class. Now I have 2 classes, they're created sametime, so how to I connect with together? below is all my code, first class has a button, and second class has a label, I want to when user click on the button in first class, label in second class will be changed. They're put in stackWidget:
// file.h
#include <QWidget>
#include <QtGui>
class widgetA;
class widgetB;
class A : public QWidget
{
Q_OBJECT
public:
explicit A(QWidget *parent = 0);
private:
QComboBox* comboBox;
QStackedWidget* stackWidget;
widgetA *wa;
widgetB *wb;
};
class widgetA : public QWidget
{
Q_OBJECT
public:
widgetA(QWidget *parent = 0);
public slots:
void buttonClicked();
private:
QPushButton* button;
};
class widgetB : public QWidget
{
Q_OBJECT
public slots:
void labelChangeText(const QString);
public:
widgetB(QWidget *parent = 0);
QLabel* label;
};
And this's cpp file:
//file.cpp
#include "a.h"
A::A(QWidget *parent) :
QWidget(parent)
{
comboBox = new QComboBox(this);
comboBox->addItem(tr("Widget A"));
comboBox->addItem(tr("Widget B"));
wa = new widgetA(this);
wb = new widgetB(this);
stackWidget = new QStackedWidget(this);
stackWidget->addWidget(wa);
stackWidget->addWidget(wb);
stackWidget->setCurrentIndex(0);
connect(comboBox, SIGNAL(currentIndexChanged(int)), stackWidget, SLOT(setCurrentIndex(int)));
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget(comboBox);
layout->addWidget(stackWidget);
setLayout(layout);
}
widgetA::widgetA(QWidget *parent):
QWidget(parent)
{
button = new QPushButton(tr("Click"));
connect(button, SIGNAL(clicked()), this, SLOT(buttonClicked()));
QHBoxLayout* lay = new QHBoxLayout;
lay->addWidget(button);
setLayout(lay);
}
void widgetA::buttonClicked()
{
// what I have to do at there for call the function at widgetB class?
}
widgetB::widgetB(QWidget *parent):
QWidget(parent)
{
label = new QLabel("....");
QHBoxLayout* lay = new QHBoxLayout;
lay->addWidget(label);
setLayout(lay);
}
void widgetB::labelChangeText(const QString text)
{
label->setText(text);
}
P/S: sorry my english
You can either pass a pointer of widgetB object to widgetA, or you can connect a signal from widgetA to a slot in widgetB.
Here's an example of the signal/slot option:
// widgeta.h
signals:
void changeText(QString text);
-
// widgeta.cpp
void widgetA::buttonClicked()
{
emit changeText("button clicked");
}
-
//widgetb.h
public slots:
void labelChangeText(const QString & text);
-
// a.cpp
connect(wa, SIGNAL(changeText(QString)), wb, SLOT(labelChangeText(QString)));
What hinders you to call wb->labelChangeText("some string") in widgetA::buttonClicked()? You have a pointer to widgetB in class A. And labelChangeText is public in class B. Just that it is a slot does not mean that you cannot call it as a normal method.
I have
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void getData();
private:
Ui::MainWindow *ui;
Dialog *second;
};
and
class Dialog: public QDialog {
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0); QDialog * dialog;
QPushButton *pushButton;
QPushButton *pushButton_2;
};
and I can connect pushbuttons in class Dialog with function getData() in class MainWindow (Dialog is a child of class Mainwindow)
I tried
connect(*second->pushButton, SIGNAL(clicked()), this,
SLOT(getData()));
but I got
error: no matching function for call to
‘MainWindow::connect(QPushButton&, const char [11], MainWindow* const, const char [11])’
How do i connect them?
if the dialog is child of QMainWindow subclass (as it would be) you should have something like:
MainWindow::MainWindow(...)
{
....
m_dialog = new Dialog(this);// in .h file it is defined as: "Dialog *m_dialog;"
....
connect(m_dialog->pushButton, SIGNAL(clicked()), this,SLOT(getData()));
}
you don't have to write:
connect(*m_dialog->pushButton, SIGNAL(clicked()), this,SLOT(getData()));
take a look at this qt code:
Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)),
&b, SLOT(setValue(int)));
a.setValue(12); // a.value() == 12, b.value() == 12
b.setValue(48); // a.value() == 12, b.value() == 48
as you can see you must use pointer and not QObject.
I'm trying to create a menu in Qt following this example http://doc.qt.nokia.com/latest/mainwindows-menus.html
but I keep getting the error 'menuBar' not declared in this scope
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
In context:
#include <QtGui>
#include "borderlayout.h"
#include "window.h"
Window::Window()
{
QTextBrowser *centralWidget = new QTextBrowser;
//***Change this to whatever widget(s) the drawing area is. QPainter or something?
centralWidget->setPlainText(tr("DRAW HERE YAY"));
BorderLayout *layout = new BorderLayout;
layout->addWidget(centralWidget, BorderLayout::Center);
layout->addWidget(createLabel("File ..."), BorderLayout::North);
layout->addWidget(createLabel("Toolbar yo!"), BorderLayout::West);
//layout->addWidget(createLabel("Status bar"), BorderLayout::South);
//Maybe we could put in a status bar. For now let's not worry about it. It's not a requirement.
setLayout(layout);
createMenus();
setWindowTitle(tr("Border Layout"));
}
QLabel *Window::createLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setFrameStyle(QFrame::Box | QFrame::Raised);
return label;
}
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
window.h
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
class QLabel;
class QMenu;
class Window : public QWidget
{
Q_OBJECT
public:
Window();
private:
void createMenus();
QLabel *createLabel(const QString &text);
QMenu *saveMenu();
};
#endif
window.cpp
#include <QtGui>
#include "borderlayout.h"
#include "window.h"
Window::Window()
{
QTextBrowser *centralWidget = new QTextBrowser;
//***Change this to whatever widget(s) the drawing area is. QPainter or something?
centralWidget->setPlainText(tr("DRAW HERE YAY"));
BorderLayout *layout = new BorderLayout;
layout->addWidget(centralWidget, BorderLayout::Center);
layout->addWidget(createLabel("File ..."), BorderLayout::North);
layout->addWidget(createLabel("Toolbar yo!"), BorderLayout::West);
//layout->addWidget(createLabel("Status bar"), BorderLayout::South);
//Maybe we could put in a status bar. For now let's not worry about it. It's not a requirement.
setLayout(layout);
createMenus();
setWindowTitle(tr("Border Layout"));
}
QLabel *Window::createLabel(const QString &text)
{
QLabel *label = new QLabel(text);
label->setFrameStyle(QFrame::Box | QFrame::Raised);
return label;
}
void Window::createMenus()
{
saveMenu = menuBar()->addMenu("&Save");
}
The menu bar is a feature of the QMainWindow class.
Because your Window class is being inherited directly from QWidget, it does not have the menuBar method, hence your error.
You need to subclass your Window class from QMainWindow rather than QWidget.