I tried maybe everything but I just don't see a mistake in this code. I made two windows inherited from QMainWindow: one with qt designer and another just in constructor. I'm trying to switch these windows in the MainWindow class depending on what buttons you press.
LoginWindow.cpp
LoginWindow::LoginWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::LoginWindow) {
ui->setupUi(this);
}
LoginWindow::~LoginWindow() {
delete ui;
}
void LoginWindow::on_confirmButton_clicked() {
emit confirmButton_clicked();
}
RegistrationWindow.hpp
RegistrationWindow::RegistrationWindow(QWidget* parent): QMainWindow(parent) {
label = new QLabel("Fast Typing"); //variable in .hpp
label->setAlignment(Qt::AlignCenter);
label->setFont(QFont("Lucida Console", 12, 2));
QVBoxLayout * l = new QVBoxLayout();
l->addWidget(label);
l->addWidget(new QLabel("Login", this));
l->addWidget(new QLineEdit(this));
l->addWidget(new QLabel("Password", this));
l->addWidget(new QLineEdit(this));
p = new QPushButton("Confirm", this); //variable in .hpp
l->addWidget(p);
w = new QWidget(); //variable in .hpp
w->setLayout(l);
setCentralWidget(w);
connect(p, &QPushButton::clicked, this, &RegistrationWindow::on_confirmButton_clicked);
}
void RegistrationWindow::on_confirmButton_clicked() {
emit confirmButton_clicked();
}
RegistrationWindow::~RegistrationWindow() { }
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
//variables in .hpp
logWindow = new LoginWindow();
regWindow = new RegistrationWindow();
goToReg();
connect(logWindow, SIGNAL(confirmButton_clicked()), this, SLOT(goToReg()));
connect(regWindow, SIGNAL(confirmButton_clicked()), this, SLOT(goToLog()));
}
void MainWindow::goToReg() {
qDebug() << "goToReg";
resize(regWindow->size());
qDebug() << "goToReg";
setCentralWidget(regWindow);
setWindowTitle("Registration");
qDebug() << "registration: " << regWindow;
qDebug() << "login: " << logWindow;
}
void MainWindow::goToLog() {
qDebug() << "goToLog";
resize(logWindow->size());
qDebug() << "goToLog";
setCentralWidget(logWindow);
setWindowTitle("Login");
qDebug() << "registration: " << regWindow;
qDebug() << "login: " << logWindow;
}
All I could say is it switches windows no matter what I make a starting window and for second time it's crashes on the line setCentralWidget() in slot with SEGV runtime error.
From the documentation of QMainWindow::setCentralWidget:
Note: QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time.
The widgets that logWindow and regWindow point to start life unowned. Then you call goToReg(), which calls setCentralWidget(regWindow) - now the main window owns *regWindow. Then you call goToLog(), which calls setCentralWidget(logWindow) - now the main window takes ownership of *logWindow and destroys *regWindow, so regWindow becomes a dangling pointer. Next time you attempt to use it, the program exhibits undefined behavior.
Related
I successfully read from a serial port with QSerialPort when I setup the instance's parameters in my main window constructor. I want my GUI to enable changing port however, but I can't seem to start reading when changing my com port after starting my application (I do so with a spinBox that sets up the COM port name of my QSerialPort instance). Here is my code (mainwindow.cpp), my problem is that if I do not directly use serial->setPortName(); in my constructor, and I put it in my slot linked to my spinBox signal, I can't read data received from my com port with qDebug anymore.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
QSerialPort *serial;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this); // Here by default. Takes a pointer to mainwindow as argument
serial = new QSerialPort(this);
qDebug() << "nb ports: " << QSerialPortInfo::availablePorts().length();
foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts())
{
qDebug() << "name" << serialPortInfo.portName();
}
qDebug() << "is " << serial->open(QSerialPort::ReadOnly);
qDebug() << "err " << serial->error();
// Create the signal and slot for
connect(ui->com_spinBox, SIGNAL(valueChanged(const QString&)),
this, SLOT(setComPort(const QString&)));
// Create the signal and slot for receiving data from device
connect(serial, SIGNAL(readyRead()), this, SLOT(serialReceived()));
}
MainWindow::~MainWindow()
{
delete ui;
serial->close(); // instance is closed when mainwindow destroyed
}
// My 2 custom slots below!!!
void MainWindow::serialReceived()
{
QByteArray ba;
ba = serial->readAll();
ui->label->setText(serial->readAll());
qDebug()<<ba;
}
void MainWindow::setComPort(const QString& com)
{
serial->close();
serial = new QSerialPort(this); // this (mainwindow) is parent
qDebug() << serial->portName();
QString comPort = "COM" + com;
qDebug() << comPort;
serial->setPortName(comPort);
serial->setBaudRate(QSerialPort::Baud9600);
serial->setDataBits(QSerialPort::Data8);
serial->setParity(QSerialPort::NoParity);
serial->setStopBits(QSerialPort::OneStop);
serial->setFlowControl(QSerialPort::NoFlowControl);
serial->open(QSerialPort::ReadOnly);
}
Here I tried moving all my serial instance setup from constructor to my slot, and close and re-open the instance to see if it helps, but I still cannot read anything with serialReceived() slot when tuning to the right COM port.. It does work if I put everything in the constructor and setPortName() with the right port number at the start of the program.
Thanks!
Try to delete and create again your QSerialPort before setPortName()
serial->deletLater();
serial = new QSerialPort(this);
serial->setPortName("COM1");
I am writing a gui in QT for controlling usb relays. I wrote a relay class which has turn on/off member functions. also wrote a custom widget which has radio buttons for controlling, a relay pointer, as well as a switchStatus() slot in which the relay turn on/off functions were called. The mainwindow has relay members. When I call the the ui->widget->switchStatus() from the mainwindow constructor, everything works fine, the relay can be turn on and off well. However, if I connect the radio button signal to switchStatus(), the program crashes whenever I click the radio button. It crashes at the line serialPort->write. But it's not about write, whatever code related to serialPort pointer it first come to will cause crash. even I want to get the port name or port address.
myWidget::myWidget(QWidget *parent) : QWidget(parent), m_ui(new Ui::Form)
{ status = 0;
m_ui->setupUi(this);
m_ui->statusIndicator->status = &status; // status in ui pointing to null before this
m_ui->turnOffButton->setChecked(true);
connect(m_ui->turnOnButton, SIGNAL(clicked(bool)), this, SLOT(switchStatus()));
//crashes when click ratioButton,
//compare to last line in the mainwindow construtor
connect(m_ui->turnOffButton, SIGNAL(clicked(bool)), this, SLOT(switchStatus()));
}
void myWidget::switchStatus()
{
qDebug() << "swithcing";
if(status)
{
setStatus(false);
}
else
{
setStatus(true);
}
m_relay->switchStatus();
}
void relay::switchStatus()
{ if(status) turnOff();
else turnOn();
}
bool relay::turnOn(){
qDebug() << writeDataOn; // test if string is correct
qDebug() << serialPort; // crashes whenever serialPort address is called
const qint64 bytesWritten = serialPort->write(writeDataOn);
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QList<QSerialPortInfo> infos = QSerialPortInfo::availablePorts();
qDebug() << infos[0].description();
QSerialPort serialPort;
serialPort.setPortName(infos[0].portName());
serialPort.setBaudRate(QSerialPort::Baud9600);
if (!serialPort.open(QIODevice::ReadWrite)) {
qDebug() << QObject::tr("Failed to open port %1, error: %2").arg(serialPort.portName()).arg(serialPort.error()) ;
}
ui->setupUi(this);
for(int i=0;i<4;i++)
{
relays[i].setRelayNumber(i);
relays[i].setPort(&serialPort);
relays[i].setStatus(relays[i].getRealStatus());
}
ui->widget->m_relay = relays;
qDebug() << ui->widget->m_relay;
qDebug() << ui->widget->m_relay->getPort();
ui->widget->switchStatus(); // this line runs well
}
Make your serial port a member of the MainWindow class. At the moment it is local to your constructor, so it is deallocated when the constructor finishes, hence the crashing. If you have declared a 'serialPort' member, you are hiding it by redeclaring it as a local scope variable inside the constructor.
I need to perform an operation when the size of a widget (MyForm) changes.
Is there a signal which is emitted when the size of a widget changes? (I could not find it in the documentation).
I need to do something like this:
#include "myform.h"
#include "ui_myform.h"
MyForm::MyForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyForm)
{
ui->setupUi(this);
connect(this, SIGNAL(sizeChanged()), this, SLOT(refresh()));
}
MyForm::~MyForm()
{
delete ui;
}
void MyForm::refresh()
{
ui->label->setText( QString::number(this->width()) + ", " + QString::number(this->height()));
}
When the widget size changes, it 'calls' the refresh function which updates a label with the current width and height. Note: it is only an example which can be easily reproduced.
Sure I can use a QTimer, for example:
#include "myform.h"
#include "ui_myform.h"
MyForm::MyForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyForm)
{
ui->setupUi(this);
timer_ = new QTimer(this);
connect(timer_, SIGNAL(timeout()), this, SLOT(refresh()));
timer_->start(100);
}
MyForm::~MyForm()
{
delete ui;
}
void MyForm::refresh()
{
ui->label->setText( QString::number(this->width()) + ", " + QString::number(this->height()));
}
But I don't think it is the best solution.
Note: I'm using Qt 5.3.
It is not necessary to create a signal, you just have to overwrite resizeEvent() and call refresh from that method:
*.h
protected:
void resizeEvent(QResizeEvent *event);
*.cpp
void MyForm::resizeEvent(QResizeEvent *event)
{
refresh();
QWidget::resizeEvent(event);
}
I am trying to pass a string (which holds the file name to an image) to a class constructor.
// pushbutton function call to open new window
void SelectTest::on_upperSideStart_clicked()
{
QString imageFile = ui->upperSideEdit->text();
uppersidewindow = new upperSideWindow(imageFile, this);
uppersidewindow->show();
}
// new class constructor
upperSideWindow::upperSideWindow(const QString &_imageFile, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::upperSideWindow)
{
ui->setupUi(this);
*image = QImage(_imageFile);
qDebug() << image->size();
}
From the debugger:
(before constructor call) imageFile =
"C:/Users/User/Documents/SpineAnalysis/Patient Name/UpperSide.JPG"
(after constructor call) imageFile =
"\001І뒴\001І뒯\001儇楌"
Why does this happen?
This appears to be a debugger issue. Using:
qDebug() << "image file: " << _imageFile
I can see that the string is still in tact.
I'm doing my first C++ - Qt4 application and I'm having some trouble "connecting" my different uis.
I have a main window with several buttons and when I click on one, I want another window to open.
The MyMainWindowClass inherits from QMainWindow and the other from QWidget.
Here is the code I have written so far :
#include <iostream>
#include "MyWidgetClass.hpp"
#include "MyMainWindowClass.hpp"
#include "ui_MyMainWindowClassUi.h"
MyMainWindowClass::MyMainWindowClass(QWidget *parent) :
QMainWindow(parent),
m_ui(new Ui::MyMainWindowClassUi)
{
m_ui->setupUi(this);
initConnect();
}
void MyMainWindowClass::initConnect()
{
QObject::connect(m_ui->SomeBtn,
SIGNAL(clicked()),
this,
SLOT(SomeBtnClicked()));
// Some other QObject::connect calls
return;
}
void MyMainWindowClass::SomeBtnClicked()
{
std::cout << "Some Btn has been clicked" << std::endl;
this->setEnabled(false);
MyWidgetClass mwc(this);
mwc.show();
return;
}
This calls the Ctor and the Dtor from MyWidgetClass, disables the MyMainWindowClassUi, but doesn't show my other GUI. What am I missing to have the window showed when I click on the button ?
Try this instead of your SomeBtnClicked method:
MyWidgetClass *mwc;
void MyMainWindowClass::SomeBtnClicked()
{
std::cout << "Some Btn has been clicked" << std::endl;
this->setEnabled(false);
if (!mwc)
mwc = new MyWidgetClass(this);
mwc->show();
mwc->raise();
mwc->setActiveWindow(); // Qt 4: activateWindow()
return;
}