Results 1 to 7 of 7

Thread: Problems with using multiple instances of the same custom widget.

  1. #1
    Join Date
    Jun 2010
    Posts
    4
    Qt products
    Qt4
    Platforms
    Windows

    Default Problems with using multiple instances of the same custom widget.

    Hi! I'm fairly new to Qt, C++ and OOP all together, but I'm working on a project as a part of a summerjob.

    I'm developing a small custom widget which will graphically display a recived value (something akin to a speedometer), and what I have made so far works to certain degree... untill I try to use more than one instance of the widget in a UI. The first instance displays correctly, but the graphical items in the second one doesn't seem to initialize. On the other hand it seems like the second instance recives input which is actually only connected to the input-slot on the first instance. My gut-feeling says it's something to do with what inherits what?

    All in all, I feel a bit confused. What precautions do you have to take when you're writing a widget meant to be reused several times in a GUI?

    The widget is built so that it can be loaded directly into QtDesigner as a plugin and I use svg-graphics (just mentioning if this could be related to the problem). I've programmed it in QtCreator.

    The widget itself is a huge mess of stuff, so I wrote a smaller example illustrating the basics of how I've made the it and which also demonstrates the same problem. It compiles without any warnings.

    In short: I can't get two instances of a selfmade widget to work in a UI, while one single one works. Example code below:

    displayclass.h
    Qt Code:
    1. #ifndef DISPLAYCLASS_H
    2. #define DISPLAYCLASS_H
    3.  
    4. #include <QtGui/QWidget>
    5. #include <QMainWindow>
    6. #include <QGraphicsView>
    7. #include <QGraphicsScene>
    8. #include <QGraphicsSvgItem>
    9. #include <QGraphicsItem>
    10. #include <QSvgRenderer>
    11. #include <QTimer>
    12. #include <QDebug>
    13. //#include <qdesignerexportwidget.h>
    14. #include <QLabel>
    15.  
    16. class /*QDESIGNER_WIDGET_EXPORT*/ displayclass : public QWidget
    17. {
    18. Q_OBJECT
    19.  
    20. public:
    21. displayclass(QWidget *parent = 0);
    22.  
    23. QSvgRenderer *svgRend;
    24. QLabel *label;
    25. QGraphicsRectItem *rectangle;
    26. QTimer *timer;
    27. void UpdateAll(double rotation, int save_angle);
    28. void DisplaySquare(double rotation);
    29. void DisplayArrow();
    30. void DisplayLabel(double rotation);
    31.  
    32. public slots:
    33. void Input(int rotation);
    34.  
    35. private slots:
    36. void Timer();
    37. };
    38.  
    39. #endif
    To copy to clipboard, switch view to plain text mode 

    displayclass.cpp
    Qt Code:
    1. #include "displayclass.h"
    2.  
    3. displayclass::displayclass(QWidget *parent) :
    4. QWidget(parent)
    5. {
    6. //Definitions
    7. scene = new QGraphicsScene(QRect(0, 0, 300, 300),this);
    8. svgRend = new QSvgRenderer(QLatin1String(":/arrow.svg"),this);
    9. view = new QGraphicsView(this);
    10. arrow = new QGraphicsSvgItem();
    11. rectangle = new QGraphicsRectItem(0,0,100,100);
    12. label = new QLabel(this);
    13.  
    14. timer = new QTimer(this);
    15. connect(timer, SIGNAL(timeout()), this, SLOT(Timer()));
    16. timer->start(30);
    17.  
    18. scene->setSceneRect(0,0,300,300);
    19. view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    20. view->setGeometry(QRect(0, 0, 350, 350));
    21. view->setScene(scene);
    22. view->show();
    23. UpdateAll(0,0);
    24. }
    25.  
    26. void displayclass::UpdateAll(double rotation, int save_angle)
    27. {
    28. static double rot=0;
    29.  
    30. if(save_angle==1)
    31. {
    32. rot=rotation;
    33. }
    34. else
    35. {
    36. DisplaySquare(rot);
    37. DisplayArrow();
    38. DisplayLabel(rot);
    39. }
    40. }
    41.  
    42. void displayclass::DisplaySquare(double rotation)
    43. {
    44. static int rectangle_activated=0;
    45.  
    46. if(rectangle_activated==0)
    47. {
    48. rectangle->setBrush( Qt::red );
    49. rectangle->setPos(0,0);
    50. qDebug()<<rectangle->pos();
    51. rectangle_activated=1;
    52. scene->addItem(rectangle);
    53. }
    54. rectangle->setRotation(rotation);
    55. }
    56.  
    57. void displayclass::DisplayArrow()
    58. {
    59. static int arrow_activated=0;
    60.  
    61. if(arrow_activated==0)
    62. {
    63. arrow->setParentItem(rectangle);
    64. arrow->setSharedRenderer(svgRend);
    65. arrow->setPos(0,0);
    66. }
    67. }
    68.  
    69. void displayclass::DisplayLabel(double rotation)
    70. {
    71. static bool label_activated=0;
    72.  
    73. if(label_activated==0)
    74. {
    75. label->setParent(this);
    76. label->setGeometry((scene->width()/2)-25,(scene->height()/2)-(label->height()/2),50,25);
    77. label->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
    78. label->setAutoFillBackground(1);
    79. label->setStyleSheet("QLabel { border-width: 2px; border-radius: 4px; border-style: solid; border-color: darkGray; background-color: white;}");
    80. label_activated=1;
    81. }
    82. label->setText(QString::number(rotation));
    83. }
    84.  
    85. void displayclass::Timer()
    86. {
    87. UpdateAll(0,0);
    88. }
    89.  
    90. void displayclass::Input(int rotation)
    91. {
    92.  
    93. UpdateAll(rotation,1);
    94.  
    95. }
    To copy to clipboard, switch view to plain text mode 

    I also attached a picture of how it looks when I use two instances in a quickly put together application.
    Both of the instances are declared like so in ui_mainwindow of the application:
    Qt Code:
    1. displayclass1 = new displayclass(centralWidget);
    2. displayclass1->setObjectName(QString::fromUtf8("displayclass1"));
    3. displayclass1->setGeometry(QRect(40, 60, 211, 231));
    4. displayclass2 = new displayclass(centralWidget);
    5. displayclass2->setObjectName(QString::fromUtf8("displayclass2"));
    6. displayclass2->setGeometry(QRect(350, 60, 201, 231));
    To copy to clipboard, switch view to plain text mode 
    Hmm, anything else I should specify if it could be helpful?

    Thanks for any help in advance! (oh and sorry for any bad English!)
    Any comments about obvious c++/Qt basics I've missed are also welcome!
    Attached Images Attached Images

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Problems with using multiple instances of the same custom widget.

    show the code where the two instances are.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. #3
    Join Date
    Jun 2010
    Posts
    4
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems with using multiple instances of the same custom widget.

    Allright, it's the form made when you start with a new, standard Qt4 GUI-application:

    Qt Code:
    1. /********************************************************************************
    2. ** Form generated from reading UI file 'mainwindow.ui'
    3. **
    4. ** Created: Wed 30. Jun 11:42:55 2010
    5. ** by: Qt User Interface Compiler version 4.6.2
    6. **
    7. ** WARNING! All changes made in this file will be lost when recompiling UI file!
    8. ********************************************************************************/
    9.  
    10. #ifndef UI_MAINWINDOW_H
    11. #define UI_MAINWINDOW_H
    12.  
    13. #include <QtCore/QVariant>
    14. #include <QtGui/QAction>
    15. #include <QtGui/QApplication>
    16. #include <QtGui/QButtonGroup>
    17. #include <QtGui/QDial>
    18. #include <QtGui/QHeaderView>
    19. #include <QtGui/QMainWindow>
    20. #include <QtGui/QMenuBar>
    21. #include <QtGui/QStatusBar>
    22. #include <QtGui/QToolBar>
    23. #include <QtGui/QWidget>
    24. #include "displayclass.h"
    25.  
    26. QT_BEGIN_NAMESPACE
    27.  
    28. class Ui_MainWindow
    29. {
    30. public:
    31. QWidget *centralWidget;
    32. QDial *dial;
    33. displayclass *displayclass1;
    34. displayclass *displayclass2;
    35. QMenuBar *menuBar;
    36. QToolBar *mainToolBar;
    37. QStatusBar *statusBar;
    38.  
    39. void setupUi(QMainWindow *MainWindow)
    40. {
    41. if (MainWindow->objectName().isEmpty())
    42. MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
    43. MainWindow->resize(600, 400);
    44. centralWidget = new QWidget(MainWindow);
    45. centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
    46. dial = new QDial(centralWidget);
    47. dial->setObjectName(QString::fromUtf8("dial"));
    48. dial->setGeometry(QRect(280, 10, 50, 64));
    49. dial->setMaximum(360);
    50. displayclass1 = new displayclass(centralWidget);
    51. displayclass1->setObjectName(QString::fromUtf8("displayclass1"));
    52. displayclass1->setGeometry(QRect(40, 60, 211, 231));
    53. displayclass2 = new displayclass(centralWidget);
    54. displayclass2->setObjectName(QString::fromUtf8("displayclass2"));
    55. displayclass2->setGeometry(QRect(350, 60, 201, 231));
    56. MainWindow->setCentralWidget(centralWidget);
    57. menuBar = new QMenuBar(MainWindow);
    58. menuBar->setObjectName(QString::fromUtf8("menuBar"));
    59. menuBar->setGeometry(QRect(0, 0, 600, 24));
    60. MainWindow->setMenuBar(menuBar);
    61. mainToolBar = new QToolBar(MainWindow);
    62. mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
    63. MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
    64. statusBar = new QStatusBar(MainWindow);
    65. statusBar->setObjectName(QString::fromUtf8("statusBar"));
    66. MainWindow->setStatusBar(statusBar);
    67.  
    68. retranslateUi(MainWindow);
    69. QObject::connect(dial, SIGNAL(valueChanged(int)), displayclass1, SLOT(Input(int)));
    70. QObject::connect(dial, SIGNAL(valueChanged(int)), displayclass2, SLOT(Input(int)));
    71.  
    72. QMetaObject::connectSlotsByName(MainWindow);
    73. } // setupUi
    74.  
    75. void retranslateUi(QMainWindow *MainWindow)
    76. {
    77. MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
    78. } // retranslateUi
    79.  
    80. };
    81.  
    82. namespace Ui {
    83. class MainWindow: public Ui_MainWindow {};
    84. } // namespace Ui
    85.  
    86. QT_END_NAMESPACE
    87.  
    88. #endif // UI_MAINWINDOW_H
    To copy to clipboard, switch view to plain text mode 


    Hmm, is instance maybe the wrong term for what I'm trying to do?

  4. #4
    Join Date
    Jun 2010
    Posts
    4
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems with using multiple instances of the same custom widget.

    Allright, having played around with it a bit, I think some of the problems originate from the static variables. Anyone who can help me confirm this?

  5. #5
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Problems with using multiple instances of the same custom widget.

    On the other hand it seems like the second instance recives input which is actually only connected to the input-slot on the first instance
    No, both instances are connected to the dial:
    Qt Code:
    1. QObject::connect(dial, SIGNAL(valueChanged(int)), displayclass1, SLOT(Input(int)));
    2. QObject::connect(dial, SIGNAL(valueChanged(int)), displayclass2, SLOT(Input(int)));
    To copy to clipboard, switch view to plain text mode 

    But I have trouble following you code.
    You have a timer that does UpdateAll(0,0); every 30 ms...
    And in addition, you react to the dial, which also indirectly calls UpdateAll() with other values...

    Can you describe what it is your application is trying to do?
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  6. #6
    Join Date
    Jun 2010
    Posts
    4
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems with using multiple instances of the same custom widget.

    Heh, I actually posted the wrong code, the Dial was only supposed to be connected to one instance.

    Mainly the application tried to provoke forth an error I've been experiencing, so it wasn't coded for elegance.
    Looks like I figured it out now. Appartently if you declare a static variable inside a function, it leads to some very strange program behaviour. I rewrote the widget without using static variables, and now it works just fine

    Chalk it up to inexperience I guess! I'll see if I can find something more specific to ask about later, but thanks for now!

  7. #7
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Problems with using multiple instances of the same custom widget.

    Looks like I figured it out now. Apparently if you declare a static variable inside a function, it leads to some very strange program behavior.
    Nothing strange about it, if you know what static means.
    I thought of this, but it actually should not be a problem in the way you implemented it, since you are creating them on the stack, per instance.
    If you were to create them as a static member, then I could understand it.
    With your implementation however, I have to think about why this actually interference between instances...
    Maybe I have to refresh on static vars...

    EDIT:
    I fell to the trap.
    Yes, static is static, basically, it gets to be global.
    So yes, the static vars are shared between all instances.
    This the reason C++ has calss members.

    Statics are only used for static classes, or static member functions, but other than that they should not be used in C++.
    Last edited by high_flyer; 1st July 2010 at 12:13.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

Similar Threads

  1. Replies: 1
    Last Post: 30th December 2008, 13:28
  2. Replies: 1
    Last Post: 1st February 2008, 18:55
  3. Problems with laying out custom widget
    By mtrpoland in forum Newbie
    Replies: 6
    Last Post: 19th August 2007, 11:43
  4. Multiple program instances
    By scwizard in forum Qt Programming
    Replies: 13
    Last Post: 1st April 2007, 17:42
  5. Replies: 0
    Last Post: 21st December 2006, 11:48

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.