A have a class, inherited from QWidget and Ui_Form (automaticaly generated class, appears when you create a .ui in Qt). It looks like
class MyClass: public QWidget, public Ui_Form {}
Ui_Form has some members, which connected with relevant widgets in the .ui file (for example, QLineEdits, QButtons, etc).
class Ui_Form {
public:
QLineEdit *fileNameEdit;
void setupUi(QWidget *Form) {
fileNameEdit = new QLineEdit(layoutWidget);
fileNameEdit->setObjectName(QStringLiteral("fileNameEdit"));
}
}
As MyClass is inherited from Ui_Form, I can use this membes. But, when I try to do something, I have an exeption "Access violation reading location". For example:
fileNameEdit->setText("String");
Can somebody give an advice?
The way you are incorporating the Ui_Form part is not how Qt proposes it by default. If you look into this button example you can see how the ui part is incorporated diferently:
Header file
#ifndef BUTTON_H
#define BUTTON_H
#include <QWidget>
namespace Ui {
class Button;
}
class Button : public QWidget
{
Q_OBJECT
public:
explicit Button(int n, QWidget *parent = 0);
~Button();
private slots:
void removeRequested();
signals:
void remove(Button* button);
private:
Ui::Button *ui;
};
#endif // BUTTON_H
CPP code
#include "button.h"
#include "ui_button.h"
Button::Button(int n, QWidget *parent) :
QWidget(parent),
ui(new Ui::Button)
{
ui->setupUi(this);
ui->pushButton->setText("Remove button "+QString::number(n));
addAction(ui->actionRemove);
connect(ui->actionRemove,SIGNAL(triggered()),this,SLOT(removeRequested()));
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(removeRequested()));
}
Button::~Button()
{
delete ui;
}
void Button::removeRequested()
{
emit remove(this);
}
The main difference is that I believe you are not calling Ui_From::setupUi function. It is clear to me that you do not need to follow the Qt suggested template (incorporating the ui as a class member rather than inheriting from it), however, it is much clearer from my point of view if you follow the Qt suggestions.
Related
I have a QT application and I'm trying to have a button in one of my windows open another window.
The way I have done my window objects so far in the main is like this:
Website control;
control.show();
This displays my first window fine and if I declare my other window in a similar way that also displays at runtime, although this is not what I want
Then in a separate header file:
class Website: public QWidget, public Ui::Website
{
public:
Website();
}
Then in the corresponding Cpp file I have:
Website::Website()
{
setupUi(this);
}
Now all this works and have added a custom slot so that when I click a button it triggers a slot in my other cpp file. The issue is I'm not sure how to show my other window as I declare them in my main so can't access them to do .show()?
Any help would be appreciated, I'm fairly new to C++ and QT
It's not clear to me what you want to do. But i might understand your struggle as I had one myself the first time approaching this framework.
So let's say you have a MainWindow class that controls the main Window view. Than you want to create a second window controlled by Website class.
You then want to connect the two classes so that when you click a button on the Website window something happens in the MainWindow.
I made a simple example for you that is also on GitHub:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "website.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void changeText();
private slots:
void on_openButton_clicked();
private:
Ui::MainWindow *ui;
//You want to keep a pointer to a new Website window
Website* webWindow;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::changeText()
{
ui->text->setText("New Text");
delete webWindow;
}
void MainWindow::on_openButton_clicked()
{
webWindow = new Website();
QObject::connect(webWindow, SIGNAL(buttonPressed()), this, SLOT(changeText()));
webWindow->show();
}
website.h
#ifndef WEBSITE_H
#define WEBSITE_H
#include <QDialog>
namespace Ui {
class Website;
}
class Website : public QDialog
{
Q_OBJECT
public:
explicit Website(QWidget *parent = 0);
~Website();
signals:
void buttonPressed();
private slots:
void on_changeButton_clicked();
private:
Ui::Website *ui;
};
#endif // WEBSITE_H
website.cpp
#include "website.h"
#include "ui_website.h"
Website::Website(QWidget *parent) :
QDialog(parent),
ui(new Ui::Website)
{
ui->setupUi(this);
}
Website::~Website()
{
delete ui;
}
void Website::on_changeButton_clicked()
{
emit buttonPressed();
}
Project composed:
SOURCES += main.cpp\
mainwindow.cpp \
website.cpp
HEADERS += mainwindow.h \
website.h
FORMS += mainwindow.ui \
website.ui
Consider the Uis to be composed:
Main Window: a label called "text" and a button called "openButton"
Website Window: a button called "changeButton"
So the keypoints are the connections between signals and slots and the management of windows pointers or references.
Material class has a mainwindow with a menu bar. When i click one of the elements in the menu bar i want to open the Fiction Qdialog window.
material.h
#ifndef MATERIALS_H
#define MATERIALS_H
#include <QMainWindow>
#include "materialinner.h"
class FictionSection;
namespace Ui {
class Materials;
}
class Materials : public QMainWindow, public MaterialInner
{
Q_OBJECT
public:
explicit Materials(QWidget *parent = 0);
~Materials();
private:
Ui::Materials *ui;
FictionSection *fiction;
};
#endif // MATERIALS_H
materials.cpp
#include "materials.h"
#include "ui_materials.h"
#include "fictionsection.h"
#include <QDebug>
#include <QMessageBox>
Materials::Materials(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Materials)
{
ui->setupUi(this);
// connect(ui->ficti,SIGNAL(textChanged(const QString &)),this,SLOT(displaySearch()));
}
Materials::~Materials()
{
delete ui;
}
void Materials::on_actionFiction_section_triggered()
{
this->hide();
fiction = new FictionSection();
fiction->show();
}
fictionsection.h
#ifndef FICTIONSECTION_H
#define FICTIONSECTION_H
#include <QDialog>
#include "materials.h"
namespace Ui {
class FictionSection;
}
class FictionSection : public QDialog, public Materials
{
Q_OBJECT
public:
explicit FictionSection(QWidget *parent = 0);
~FictionSection();
private:
Ui::FictionSection *ui;
};
#endif // FICTIONSECTION_H
When i compile it gives an error which is
Request for member 'show' is ambiguous.
Please help me to solve this. Thank you in advance.
The problem is that your FictionSection class inherits from both QDialog and Materials, but your Materials class also inherits from QMainWindow. Both QMainWindow and QDialog have a virtual show() method (inherited from QWidget), which causes the ambiguity. In other words: do you intend to call QMainWindow::show's implementation or QDialog::show's implementation? No one knows.
To solve this, you should use inheritance properly. Inherit from either QMainWindow or QDialog, but not both.
You need to understand why it is that you're inheriting the way you are (which is wrong) and improve the logic of the relationship between your classes to avoid problems like this one.
Also, class names should be singular, so Materials should be Material. If it needs to handle multiple things, then it could be MaterialManager or something similar.
I recently started programming in C ++ and am having some difficulties in relation to the exchange of data between classes.
I searched many tutorials and examples, but none worked. I finally decided to ask for help because I do not know what do ...
PS: I want to call keyPressEvent function from my B (solEditor) class
thanks.
addons/soleditor.h (class)
#include <Qsci/qsciscintilla.h>
#include <QWidget>
#include <QKeyEvent>
class Editor; // main class
class solEditor : public QsciScintilla
{
public:
explicit solEditor(QWidget *parent = 0);
Editor editor; // error <<
protected:
void keyPressEvent(QKeyEvent *e);
};
editor.h (main window)
#include <QMainWindow>
#include "about.h"
#include "data.h"
#include "addons/codeeditor.h"
#include "addons/highlighter.h"
#include "addons/soleditor.h"
#include "plugins/headergenerator.h"
#include "plugins/updatescreen.h"
namespace Ui {
class Editor;
}
class solEditor;
class Editor : public QMainWindow
{
Q_OBJECT
solEditor *sE;
public:
QsciScintilla* ce;
Highlighter *Hl;
solEditor *e;
Ui::Editor *ui;
explicit Editor(QWidget *parent = 0);
~Editor();
public slots:
void on_KeyPress(QKeyEvent *e);
};
Error:
SOLEditor\addons\soleditor.h:14: error: C2079: 'solEditor::editor' uses undefined class 'Editor'
You are using a forward declaration
class Editor; // main class
with a local instance of that class
Editor editor; // error <<
Unfortunately, that is not possible, as in this case the compiler needs to know the full details of the Editor class.
There are two possible solutions:
Make the member a pointer: Editor* editor
Use an #include instead of a forward declaration.
If you want to make your code flexible, you could do it like this:
class solEditor : public QsciScintilla
{
public:
explicit solEditor(Editor* editor, QWidget* parent = 0);
inline Editor* editor() const { return _editor; }
private:
Editor* _editor;
}
and in the cpp file:
solEditor::solEditor(Editor* editor, QWidget* parent)
// TODO: call parent constructor
{
_editor = editor;
}
solEditor::~solEditor()
{
_editor = NULL;
}
You can then create a solEditor instance like this:
QWidget* optionalParentWidget = GetParentWidgetFromSomewhere();
Editor* editor = GetEditorInstanceFromSomewhere(); // or create it yourself
solEditor* myEditor = new solEditor(editor, optionalParentWidget);
(As a side node, classes in C++ usually start with a capital letter: QWidget, Editor, SolEditor. That makes it easier to spot if something is a class, a function or a variable).
About the key press event: If you want one class to handle certain events of another class, it's best to use the eventFilter mechanism:
http://qt-project.org/doc/qt-5/qobject.html#installEventFilter
In Qt C++, is it possible to create a custom QWidget and then reuse this custom QWidget for all QWidget (that inherit all from the custom QWidget) of the project?
Maybe I have misunderstood the question, but you can just create your custom QWidget, then use it everywhere.
class derivedQWidget : public QWidget
{
Q_OBJECT
derivedQWidget();
virtual ~derivedQWidget();
}
class myWidget : public derivedQWidget
{
...
}
class myWidget2 : public derivedQWidget
{
...
}
If the question is: Can we reimplement QWidget?, no you can't.
i have solved in this mode:
the first class, Widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QPushButton>
#include <QMouseEvent>
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
virtual ~Widget();
QPushButton *getBtn() const;
void setBtn(QPushButton *value);
protected:
void mousePressEvent(QMouseEvent *evt);
void mouseMoveEvent(QMouseEvent *evt);
private:
Ui::Widget *ui;
QPushButton *btn;
QPoint oldPos;
};
and the second class widExt.h, that inherit from Widget:
#ifndef WIDEXT_H
#define WIDEXT_H
#include "widget.h"
namespace Ui {
class widExt;
}
class widExt : public Widget
{
public:
widExt();
private slots:
void on_dial_2_actionTriggered(int action);
private:
Ui::widExt *ui;
};
#endif // WIDEXT_H
with the relative widExt.cpp:
#include "widext.h"
#include "ui_widext.h"
widExt::widExt() : ui(new Ui::widExt)
{
ui->setupUi(this);
}
void widExt::on_dial_2_actionTriggered(int action)
{
}
in this mode, i inherit all from the first class and i can customize other classes independently.
I'm a Qt newbie and all I'm trying to do is create a custom QLineEdit class with a few customizations (default alignment and default text). Right now I'm just trying to establish a base class, inheriting only QWidget. This is what I have (very bad code I know):
userText (utxt.h):
#ifndef UTXT_H
#define UTXT_H
#include <QWidget>
#include <QLineEdit>
class utxt : public QWidget
{
Q_OBJECT
public:
explicit utxt(QWidget *parent = 0);
QString text () const;
const QString displayText;
Qt::Alignment alignment;
void setAlignment(Qt::Alignment);
signals:
public slots:
};
#endif // UTXT_H
utxt.cpp:
#include "utxt.h"
utxt::utxt(QWidget *parent) :
QWidget(parent)
{
QString utxt::text()
{
return this->displayText;
}
void utxt::setAlignment(Qt::Alignment align)
{
this->alignment = align;
}
}
I know this is really wrong, and I keep getting "local function definition is illegal" errors on the two functions in utxt.cpp. Can someone please point me in the right direction? I'm just trying to create a custom QLineEdit to promote my other line edits to.
QLineEdit already has the alignment that can be set and also placeholderText.
LE: As I said there is no need to inherit from QLineEdit (or QWidget) for this functionality, but if you really want to do it you can just create your class and code a constructor that takes the parameters you want and call QLineEdit's functionality with that, something like:
//in the header
//... i skipped the include guards and headers
class utxt : public QLineEdit
{
Q_OBJECT
public:
//you can provide default values for all the parameters or hard code it into the calls made from the constructor's definition
utxt(const QString& defaultText = "test text", Qt::Alignment align = Qt::AlignRight, QWidget *parent = 0);
};
//in the cpp
utxt::utxt(const QString& defaultText, Qt::Alignment alignement, QWidget *parent) : QLineEdit(parent)
{
//call setPlaceHolder with a parameter or hard-code the default
setPlaceholderText(defaultText);
//same with the default alignement
setAlignment(alignement);
}