Unsolved TrafficLight example as a widget in MainWindow
-
Hi everybody,
I have a problem and I don't know what to do.
I want to use the trafficlight example as a smaller widget in my mainwindow. So that the trafficlight is running in my mainwindow and not as a seperate window.What I have done....
I used the source code of the trafficlight example and divided it into more files (seperated the classes to files). Then I modified the code at some places to get more overview. At last I create my mainwindow class and there I show my trafficlightwidget.My problem...
The trafficlightwidget will be displayed in my mainwindow, as I want (black area). But the lightwidgets (green, yellow, red) will not be shown. When I show my trafficlightwidget in a seperate window everything is fine. But within the mainwindow it don't show the lightwidgets.
I have also tried to use the update() function of the trafficlightwidget and the mainwindow, but nothing happens. :-(Can anybody help me? Thank you in advance!!!
Best regards
TobiasMy code:
main.cppint main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; TrafficLightWidget tl; TrafficLightController tlc; QObject::connect(&tlc, SIGNAL(greenChanged(bool)), &tl, SLOT(greenisOn(bool))); QObject::connect(&tlc, SIGNAL(yellowChanged(bool)), &tl, SLOT(yellowisOn(bool))); QObject::connect(&tlc, SIGNAL(redChanged(bool)), &tl, SLOT(redisOn(bool))); w.show(); return a.exec(); }
mainwindow.h
namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; TrafficLightWidget * trafficlight; };
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); trafficlight = new TrafficLightWidget(this); trafficlight->setGeometry(50,50,100,275); trafficlight->show(); } MainWindow::~MainWindow() { delete ui; }
trafficlightwidget.h
class TrafficLightWidget : public QWidget { Q_OBJECT public: explicit TrafficLightWidget(QWidget *parent = 0); ~TrafficLightWidget(); public slots: void greenisOn(bool on); void yellowisOn(bool on); void redisOn(bool on); protected: void paintEvent(QPaintEvent * paint); private: TrafficLightWidget *ui; LightWidget *red; LightWidget *yellow; LightWidget *green; QVBoxLayout *vbox; };
trafficlightwidget.cpp
TrafficLightWidget::TrafficLightWidget(QWidget *parent) : QWidget(parent) { vbox = new QVBoxLayout(this); red = new LightWidget(Qt::red, this); yellow = new LightWidget(Qt::yellow, this); green = new LightWidget(Qt::green, this); vbox->addWidget(red); vbox->addWidget(yellow); vbox->addWidget(green); QPalette pal = this->palette(); pal.setColor(QPalette::Background, Qt::black); this->setPalette(pal); this->setAutoFillBackground(true); } TrafficLightWidget::~TrafficLightWidget() { } void TrafficLightWidget::greenisOn(bool on) { if (on == true) { green->turnOn(); } else { green->turnOff(); } } void TrafficLightWidget::yellowisOn(bool on) { if (on == true) { yellow->turnOn(); } else { yellow->turnOff(); } } void TrafficLightWidget::redisOn(bool on) { if (on == true) { red->turnOn(); } else { red->turnOff(); } } void TrafficLightWidget::paintEvent(QPaintEvent *paint) { }
lightwidget.h
class LightWidget : public QWidget { Q_OBJECT Q_PROPERTY(bool on READ isOn WRITE setOn) public: explicit LightWidget(const QColor &color, QWidget *parent = nullptr); bool isOn(); void setOn(bool on); public slots: void turnOff(); void turnOn(); protected: void paintEvent(QPaintEvent * paint); private: QColor light_color; bool light_on; };
lightwidget.cpp
LightWidget::LightWidget(const QColor &color, QWidget *parent) : QWidget(parent) { light_color = color; light_on = false; } bool LightWidget::isOn() { return light_on; } void LightWidget::setOn(bool on) { if (on == light_on) { return; } light_on = on; this->update(); } void LightWidget::turnOff() { setOn(false); } void LightWidget::turnOn() { setOn(true); } void LightWidget::paintEvent(QPaintEvent *paint) { if (!light_on) { return; } QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setBrush(light_color); painter.drawEllipse(0, 0, width(), height()); }
trafficlightcontroller.h
class TrafficLightController : public QObject { Q_OBJECT Q_PROPERTY(bool redOn READ getred WRITE setred NOTIFY redChanged) Q_PROPERTY(bool yellowOn READ getyellow WRITE setyellow NOTIFY yellowChanged) Q_PROPERTY(bool greenOn READ getgreen WRITE setgreen NOTIFY greenChanged) public: explicit TrafficLightController(QObject *parent = nullptr); bool getred(); bool getgreen(); bool getyellow(); void setred(bool on); void setgreen(bool on); void setyellow(bool on); signals: void redChanged(bool on); void greenChanged(bool on); void yellowChanged(bool on); private: QStateMachine *machine; QState *greenState; QState *redState; QState *yellowState; QState *redyellowState; QTimer *timer; bool green; bool red; bool yellow; };
trafficlightcontroller.cpp
TrafficLightController::TrafficLightController(QObject *parent) : QObject(parent) { machine = new QStateMachine(this); redState = new QState(machine); yellowState = new QState(machine); greenState = new QState(machine); redyellowState = new QState(machine); timer = new QTimer(machine); green = false; red = false; yellow = false; redState->assignProperty(this, "redOn", true); redState->assignProperty(this, "yellowOn", false); redState->assignProperty(this, "greenOn", false); redState->assignProperty(timer, "interval", 2000); yellowState->assignProperty(this, "redOn", false); yellowState->assignProperty(this, "yellowOn", true); yellowState->assignProperty(this, "greenOn", false); yellowState->assignProperty(timer, "interval", 2000); greenState->assignProperty(this, "redOn", false); greenState->assignProperty(this, "yellowOn", false); greenState->assignProperty(this, "greenOn", true); greenState->assignProperty(timer, "interval", 2000); redyellowState->assignProperty(this, "redOn", true); redyellowState->assignProperty(this, "yellowOn", true); redyellowState->assignProperty(this, "greenOn", false); redyellowState->assignProperty(timer, "interval", 2000); redState->addTransition(timer, SIGNAL(timeout()), redyellowState); redyellowState->addTransition(timer, SIGNAL(timeout()), greenState); greenState->addTransition(timer, SIGNAL(timeout()), yellowState); yellowState->addTransition(timer, SIGNAL(timeout()), redState); machine->setInitialState(redState); machine->start(); timer->start(); } void TrafficLightController::setred(bool on) { if (red != on) { red = on; emit redChanged(on); } } void TrafficLightController::setgreen(bool on) { if (green != on) { green = on; emit greenChanged(on); } } void TrafficLightController::setyellow(bool on) { if (yellow != on) { yellow = on; emit yellowChanged(on); } } bool TrafficLightController::getred() { return red; } bool TrafficLightController::getgreen() { return green; } bool TrafficLightController::getyellow() { return yellow; }
-
Hi
when you use TrafficLightWidget in main window, do you remember to hook it up to a TrafficLightController ?
Like show in main.cpp ?QObject::connect(&tlc, SIGNAL(greenChanged(bool)), &tl, SLOT(greenisOn(bool))); QObject::connect(&tlc, SIGNAL(yellowChanged(bool)), &tl, SLOT(yellowisOn(bool))); QObject::connect(&tlc, SIGNAL(redChanged(bool)), &tl, SLOT(redisOn(bool)));
-
What do you mean exactly?
I have already tried to update mainwindow as well as trafficlightwidget with this 3 signals.
-
That the code shown des not seems to connect but i could have missed it.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
trafficlight = new TrafficLightWidget(this);no controller and no connects. ?
-
I have tried to connect it in main.cpp and in the constructor of mainwindow.cpp.
(This lines are not shown in the above code)
But it didn't work.I tried:
QObject::connect(&tlc, SIGNAL(lightChanged()), &tl, SLOT(repaint()));
QObject::connect(&tlc, SIGNAL(lightChanged()), &tl, SLOT(update()));
QObject::connect(&tlc, SIGNAL(lightChanged()), &tl, SLOT(show())); -
When you tried in constructor, did you remember to new the TrafficLightController also ?
if you did
TrafficLightController tlc;it would be deleted as soon as main window constructor was finished.
the code from main.cpp can not just be copied to main window.
The objects need to be NEW.ed. -
In the constructor of mainwindow I tried this version:
TrafficLightController * controller = new TrafficLightController();
connect(controller, SIGNAL(lightChanged()), this, SLOT(repaint()));
connect(controller, SIGNAL(lightChanged()), this, SLOT(update()));
connect(controller, SIGNAL(lightChanged()), this, SLOT(show())); -
but in original it was greenisOn(bool)
is that the same as some widget update ???
in original its from
TrafficLightController to the TrafficLightWidget ?
should that still not be the case???
-
Now I tried this versions in mainwindow constructor.
controller = new TrafficLightController();
connect(controller, SIGNAL(lightChanged()), trafficlight, SLOT(repaint()));
connect(controller, SIGNAL(lightChanged()), trafficlight, SLOT(update()));
connect(controller, SIGNAL(greenChanged(bool)), trafficlight, SLOT(greenisOn(bool)));green = new LightWidget(Qt::green); red = new LightWidget(Qt::red); yellow = new LightWidget(Qt::yellow); connect(controller, SIGNAL(lightChanged()), red, SLOT(repaint())); connect(controller, SIGNAL(lightChanged()), green, SLOT(update())); connect(controller, SIGNAL(lightChanged()), yellow, SLOT(greenisOn(bool)));
-
Hi
The only difference from main should be.
TrafficLightWidget tl = new TrafficLightWidget ; TrafficLightController tlc =new TrafficLightController; QObject::connect(tlc, SIGNAL(greenChanged(bool)), tl, SLOT(greenisOn(bool))); QObject::connect(tlc, SIGNAL(yellowChanged(bool)), tl, SLOT(yellowisOn(bool))); QObject::connect(tlc, SIGNAL(redChanged(bool)), &tl, SLOT(redisOn(bool)));
unless you change some other code. ??
If it could paint by itself in main.cpp
there should be no need to connect to update/repaint even if you
now do it in main window. It works the same regardless of what
it is put into. -
@Tobias89 I took traffic light example and using Qt Creator created default new project (Qt Widgets Application) and added individual Qt classes (LightWidget, TrafficLightWidget and TrafficLight, all based on QWidget). So far it should be pretty much what I imagine you have done.
Then I used Qt Creator to edit the only form in the project (mainwindow.ui) and added a Widget object from component palette (section Containers). The magic now is to promote that QWidget into the TrafficLight class, and that's it. No need to do anything else in main.cpp. Please see mine below, no references to any widget, as the TrafficLight component is encapsulated into QMainWindow (because you added it with the form designer)
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
You may have more info about Integrating a Custom Widget into Qt Designer here.
-
To promote is the correct keyword, I think.
But it still didn't refresh, when a light changes. -
-
@Pablo-J-Rogina
Thanks a lot!!
This works fantastic! :-)