Overall Code Design and Widget Editing [Solved]
-
So I am looking for a little advise on how to setup my code properly with classes and such. As of right now I am working on a project that has one main window, and multiple widgets on the main window (including a Qwt plot).
The way I currently have it setup is I have multiple class files and within these class files, other widgets are created.
For example, I have a button sidebar on my main window. My class is buttonsidebar, and when an instance of the button sidebar is created in the main window, 4 buttons are created and setup in a vbox layout within the class file initialization.
main window code:
@
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
// qwt plot
QWidget *plot = new graph(this); // graph widget
plot->setGeometry(4, 31, 1005, 585); // graph size
// progress bar
QWidget *progressbar = new loadbar(this); // load bar widget
progressbar->setGeometry(715, 643, 340, 41); // load bar size
// button side bar 1
QWidget *btsidebar = new buttonsidebar(this); // side bar widget
btsidebar->setGeometry(1002, 24, 160, 160); // side bar size
// grid side bar 1
QWidget *informationsidebar = new infosidebar(this);
informationsidebar->setGeometry(1004, 207, 158, 200);
}
@here is an example of the class files:
Qwt Plot:
@
graph::graph(QWidget *parent):
QwtPlot(parent)
{
// setup all information for the qwt plot
}
@Button Sidebar:
@
buttonsidebar::buttonsidebar(QWidget *parent) :
QWidget(parent)
{
// create push buttons in widget
QPushButton *bt1 = new QPushButton("1", this);
QPushButton *bt2 = new QPushButton("2", this);
QPushButton *bt3 = new QPushButton("3", this);// create vbox layout QVBoxLayout *sidebar = new QVBoxLayout(this); // create vertical layout sidebar->setSpacing(0); // button spacing to 0 // and more code proceeds from there
}
@Now, I wanted to create all of my objects in code so i could deal with resizeing and what not without the designer. Yet, I am running into the issue on how I am able to edit certain things about the widgets created in the main window.
For example, when I want to have an axis change to the QwtPlot plot, does this absolutely need to be done within the main window since the class was created in the main window? or can it be done anywhere in the project? I did try to make the instance global, but I am still unable to successfully edit the plot.
I have another class that processes data and puts some values into vectors to create a line on the Qwt Plot, I am having a hard time adding a line to the QwtPlot "plot".
What would be the proper way to edit a widget created in the main window and change its properties from another class??
Is this setup ok? or is there a better way to layout my design.
Thanks people, I am new to Qt and am learning from a C-programming background so I would like to learn the proper way since I see myself using Qt quite a bit in the near future.
-
Signals and Slots will probably help in you controlling or updating one widget from another. That decouples the need for each widget to know about each other.
For instance, the class that processes data can emit a signal containing the data to be added, and a subclass of the QwtPlot class can have a slot which receives the data and adds it to itself.
There are a lot of good examples in the documentation.
Edit: Rewrote the second sentence so that it actually makes sense.
-
Just a remark/question: In MainWindow's constructor, you instantiate a Ui::MainWindow in member ui, but you never call ui->setupUi(this). Is this by accident?
Regarding the resizing, I would suggest to put the component's widgets like buttonsidebar, etc. in a layout, this way Qt handles everything for you.
For the update, signals and slots seem appropriate, as mlong already wrote. You can easily define your own properties, signals and slots for your widgets and connect those.
-
A few additional thoughts:
In your MainWindow class above, while it is technically legal to use QWidget* to hold pointers to your widgets (since they are QWidget subclasses), it's better to use pointers to their own types (graph* , loadbar*, etc.) in order to easily get full access to any additional methods or member variables which you declare in your subclass.
You mentioned making widgets global. That's generally always a bad idea. In fact, in most cases, making anything global is usually a bad idea and is a good indication that you need to review your design.
As Volker mentioned, if you're creating all your widgets in code, you probably don't need the ui(...) in your MainWindow constructor (and its declaration).
-
Thank you for the input! I am actually running into an issue now though. I read up on how to communicate between two objects using signals and slots.
connect(object1, signal, object2, slot)
then use emit to trigger the signal to transfer data.
Now I am having the issue that, I have a class file that processes a csv file, and within the csv file, I need to emit a signal that sets the axis's of the QwtPlot, is this impossible since my signal is not an "object", I declared my function in my header file for the processcsv class as a signal, but what would I denote as the object?
For example:
I have a class file for my QwtPlot as shown above. This class file has 4 functions within the class that set Axis Scales, Adds a Curve to the plot, etc.
I have another class file that processes csv files containing multiple functions as well to go through the steps of parsing all the data.
I want to emit a signal from my processcsv class, to change the axis scale of the QwtPlot.
Is this possible?
Edit: Just to clarify, I changed the object pointers in the mainwindow code, and the setupUI is there in the code, I just miss copied it when defining the example :)
-
bq. I need to emit a signal that sets the axis’s of the QwtPlot, is this impossible since my signal is not an “object”
I'm not sure what you mean by this. If you make your Csv-reading class a subclass of QObject, then you can create any signals you'd like, which can emit any data that you like.
Here's an off-the-top-of-my-head example (since I'm not familiar with your classes, let's just assume you want to pass a double scale value for the x and y axis, just for the sake of argument.)
If you had
@
class MyCsvReader : public QObject
{
Q_OBJECT
...
signal:
void newAxisData(double xscale, double yscale);};
class MyQwtPlot : public QwtPlot
{
Q_OBJECT
...public slots:
handleAxisDataChanged(double xscale, double yscale);
};SomeOtherClass::someInitFunction()
{
MyCsvReader *reader = new MyCsvReader();
MyQwtPlot *plotter = new MyQwtPlot();
connect(reader, SIGNAL(void newAxisData(double, double))
plotter, SLOT( handleAxisDataChanged(double, double )));
}
@In your MyQwtPlot class, you'd implement handleAxisDataChanged(...) to do the work of setting your axis data, using whatever the normal methods are, using the two doubles that were passed in as parameters.
Then in your csv reader class, as you read your data and you'd like to change your axis data, just use
@ emit void newAxisData(123.45, 67.890); @
which would call handleAxisDataChanged() in your plotter class and, thus, set your axis scales. -
Thank you very much! This helped a lot! I actually was creating an instance of the class in a separate section of the code so I was a little confused on how to connect the two. But this was great help and it seems to be working great. I feel like I have the conceptual part of it down now as well. Thank you again!