Using Qt Creator (with Qwt), really basic stuff - qt

I'm trying to make a Qt program using Qt Creator and Qwt for plotting. I've never used Qt Creator before. I've created a MainWindow and added a Qwtplot widget there (object name: qwtPlot). The widget shows up in the program when I compile and run it. But theres no mention of the qwtPlot object anywhere in the (autogenerated) code so I assume it is being added at compile time from the .ui xml file (or something).
My question is that... how do I modify/change the qwtPlot object? Or where should I place the code?
I'm having a hard time articulating my question but the question basically is "How do I do anything with the qwtPlot widget which is created (graphically) with Qtcreator?". I've checked some tutorials but in the tutorials they add the widgets manually in the code, but I'd like to use Qt Creator (because my UI will be fairly complicated). This whole Qt Creator is pretty confusing...

A typical solution is to use multiple inheritance or contain the UI component as a private member. Qt explains the process on their web site:
Using a Designer UI File in Your Application
For a main window, most of this is auto-generated for you (on my version, at least ... 2.0.1)
You should have (or create) a mainwindow.h file that contains a member of type Ui::MainWindow.
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
Your mainwindow.cpp should initialize it properly, and then you can get to the auto-generated members through the private ui member.
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
ui->setupUi(this);
ui->myControl->setProperty(...);
}
MainWindow::~MainWindow() {
delete ui;
}
If you use the multiple-inheritance method, you can access the members directly.

Related

SIGSEGV when adding widget in Qt

I implemented example (chapter 2) from "Mastering Qt 5" book but the code crashes when adding widget to centralWidget's layout:
ui->centralWidget->layout()->addWidget(&mCpuWidget)
I suspect that the centralWidget does not have layout, hence it crashes but I don't know how to fix that?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
mCpuWidget(this)
{
ui->setupUi(this);
SysInfo::instance().init();
ui->centralWidget->layout()->addWidget(&mCpuWidget);
}
Here are two more classes which might help figure out the problem. Some of you might have the book too with all of the code (hence I mentioned it).
CpuWidget::CpuWidget(QWidget* parent):
SysInfoWidget(parent),
mSeries (new QPieSeries (this))
{
mSeries->setHoleSize(0.35);
mSeries->append("CPU Load", 30.0);
mSeries->append("CPU Free", 70.0);
QChart* chart = chartView().chart();
chart->addSeries(mSeries);
chart->setTitle("CPU Average Load");
}
This class creates and sets layout (QVBoxLayout)
SysInfoWidget::SysInfoWidget(QWidget *parent, int startDelayMs, int updateSeriesDelayMs) :
QWidget(parent),
mChartView(this)
{
mRefreshTimer.setInterval(updateSeriesDelayMs);
connect(&mRefreshTimer, &QTimer::timeout,
this, &SysInfoWidget::updateSeries);
QTimer::singleShot(startDelayMs,
[this] {mRefreshTimer.start();});
mChartView.setRenderHint(QPainter::Antialiasing);
mChartView.chart()->legend()->setVisible(false);
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(&mChartView);
setLayout(layout);
}
I'm the co-author of the book "Mastering Qt 5" !
I guess your suspicion about the layout is correct:
ui->centralWidget->layout()->addWidget(&mCpuWidget);
Without any layout defined the returned item is null so you can't call the method layout().
If you have some errors during your learning you should refer to the final source code hosted on github here: https://github.com/PacktPublishing/Mastering-Qt-5
Take a look to the the file "Mastering-Qt-5/Chapter_02/MainWindow.ui":
<ui version="4.0">
...
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout"/>
</widget>
...
</ui>
As you can see for this project, a horizontalLayout of type QHBoxLayout is defined in the centralWidget. You can easily edit a ".ui" file with a text editor from Qt Creator with the following steps:
Right-click on "MainWindow.ui" in the Project hierarchy view
Select "Open-With"
Finally "Plain text editor"
Select "Form editor" when you want to come back to the WYSIWYG editor.
As suggested in other answers, the way to do it from C++ with the following line is also correct:
ui->centralWidget->setLayout(new QHBoxLayout());
Thank you for highlighting the lack of information about the layout here. I created an issue to add an errata about this topic.
Unless I have missed something in the code you have provided you haven't actually set your central widget. By default calling QMainWindow::centralWidget() returns a NULL pointer. You need to first call QMainWindow::setCentralWidget(QWidget* yourCentralWidget) before you call it. And yes, you also need to add a layout to it if you want to use layout()->addWidget(...). You can create an instance of a generic QWidget, set its layout, set is a central widget and then work with it.
You can fix your problem either by adding a layout in C++:
ui->setupUi(this);
SysInfo::instance().init();
ui->centralWidget->setLayout(new QVBoxLayout()); // Or any other layout class
ui->centralWidget->layout()->addWidget(&mCpuWidget);
Or in the UI Designer by using those buttons:
Note that for the buttons to be active you need to have at least 1 widget in your central widget and then select your central widget. You can then write:
ui->setupUi(this);
SysInfo::instance().init();
// One way
ui->centralWidget->layout()->addWidget(&mCpuWidget);
// Another way
ui->layout->addWidget(&mCpuWidget);
Finally you could also move your CpuWidget to the ui file using the "Promote to..." option in the contextual menu. In this case you would not need mCpuWidget but you could access it using something like ui->cpuWidget.
For more info read the Qt Designer manual:
Using Layouts in Qt Designer
Using Custom Widgets with Qt Designer

Qt Form and main.cpp communication

i have a Qt project with mainwindow (GUI Application)
how can i communicate with my main via my form?
for example
increase variable (which there's in my main) while button a click in my form
i have make a project in C which its in console application. works fine, and now i make another project which contains ui form with same code. and i want to make communication between form and main function
You can use the Qt signal/slot functionality.
Example:
// on mainwindow.cpp. Delcare onButtonClicked as a slot() on the header
void onButtonClicked()
{
++myVar;
}
connect(myButton, SIGNAL(clicked()), this, SLOT(onButtonClicked());
Reference docs.

QTabWidget methods not available in QtDesigner

One of the methods available in the QTabWidget class is setTabEnabled - I can't see of a way to set this in QtDesigner (I know I can set it in the code) - is there a specific reason why this method (and presumably others?) aren't settable in QtDesigner?
Just change enabled property of respective widget inside QTabWidget.
according to documentation this suppose to work. I've taken a look on QTabWidget code and it looks like either documentation is wrong or there is a bug in code. I will not explain why just provide workaround on it.
Create this method:
void tabBarWorkaround(QTabWidget *tabWidget) {
for (int i=0; i<tabWidget->count(); ++i) {
tabWidget->setTabEnabled(i, tabWidget->widget(i)->isEnabled());
}
}
And use it in construction time:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
tabBarWorkaround(ui->tabWidget);
}
From this moment changing enabled property of page in designer will work like you want.
I've test this with Qt 5.2.1 and it works.
I've realised that there are two separate possible events:
unchecking the 'enabled' checkbox for a tab widget in QtDesigner actually invokes self.<tabname>.setEnabled(False), which seems to disable all child widgets within the tab, but does not disable the tab button itself(!)
Disabling the tab button so that it's not clickable is not possible in QtDesigner, but is possible in code (as discussed in the previous answer): self._uiform.<tab frame>.setTabEnabled(<tab index>,False)

Which qt widget should I use for message display?

The QStatusBar has just one line each time and I cannot track the history or save the history in a log file.
So I want to have a dock widget in my mainwindow that is able to display the messages I need in a multi-line way and auto-scrolling way and then automatically saved to a log file.
My question is how to do this in Qt?
If what you are looking for is something similar to the "Application Output" pane of QtCreator, then a simple QPlainTextEdit can do the job. You can call QPlainTextEdit::setReadOnly(true) if you don't want the user to be able to edit its content (i.e. only your application can write to it).
If you want auto-scrolling and automatically saving to a log file, you will need to subclass it though. Here's a little something to get you started:
#include <QCoreApplication>
class MyLogWindow : public QPlainTextEdit
{
Q_OBJECT
/* snip */
public:
void appendMessage(const QString& text);
private:
QFile m_logFile;
};
void MyLogWindow::appendMessage(const QString& text)
{
this->appendPlainText(text); // Adds the message to the widget
this->verticalScrollBar()->setValue(this->verticalScrollBar()->maximum()); // Scrolls to the bottom
m_logFile.write(text); // Logs to file
// optional if you want to see the changes
// after appendPlainText() immediately
// useful if you use this->appendMessage() in a loop
QCoreApplication::processEvents();
}
I leave it to you to deal with the boilerplate (opening and closing the file, dealing with newlines, etc.).
Now, simply put an instance of MyLogWindow in a dock in your QMainWindow, and call MyLogWindow::appendMessage() every time you need to log something to have it displayed, scrolled and saved automatically.

setCentralWidget not declared in scope

#include <QtGui>
#include <QWidget>
#include "notepad.h"
notepad::notepad()
{
textField = new QTextEdit;
setCentralWidget(textField);
setWindowTitle(tr("The building of a notepad...."));
}
This is a file of one of my Qt project. There is some error with the setCentralWidget part. The error is that it is not declared in the scope. But I have included the QWidget class under which it gets included. What is the mistake?
setCentralWidget is a method on QMainWindow. It is not a top-level function. It would only be in scope here if your notepad class derives from QMainWindow, which I guess it must not.
Like others have said, setCentralWidget(..) is only a member of QMainWindow. I think the behavior you are looking for can be achieved by adding a layout to your QWidget and then adding your QTextEdit to the layout. I would suggest a QPlainTextEdit as it is setup for editing multiple lines of a text document. QTextEdit is usually used for single line input. Here's some sample code:
notepad::notepad()
{
QVBoxLayout *layout = new QVBoxLayout();
QPlainTextEdit *textBox = new QPlainTextEdit();
layout->addWidget(textBox);
this->setLayout(layout);
setWindowTitle(tr("The building of a notepad...."));
}
The layout can be a QVBoxLayout, QHBoxLayout, QGridLayout, etc. It all depends on what you want to achieve with the layout of the form. You can also add to your existing layout by using this->addWidget(QWidget*) instead of using a newly created layout. I hope this helps.

Resources