Make Qlabel clickable or double clickable in Qt - c++

I am beginner in Qt, now I want to make my label clickable, I have searched so much online, but no one gives my a real example of how they made it. So can someone teach me step by step? Now my basic thinking is creating a new .c file and new .h file respectively and then include them into my mainwindow.c and then connect it with the existing label in ui form. These are what I was trying to do, but can not make it. Hope someone can teach and better put the step picture in the command, thanks.
Here is the clicklabel.h code:
#ifndef CLICKEDLABEL_H
#define CLICKEDLABEL_H
#include <QWidget>
#include <QLabel>
class ClickedLabel : public QLabel
{
Q_OBJECT
public:
ClickedLabel(QWidget *parent=0): QLabel(parent){}
~ClickedLabel() {}
signals:
void clicked(ClickedLabel* click);
protected:
void mouseReleaseEvent(QMouseEvent*);
};
#endif // CLICKEDLABEL_H
This the clicklabel.c code:
#include "clicklabel.h"
void ClickedLabel::mouseReleaseEvent(QMouseEvent *)
{
emit clicked(this);
}
These are what I added into my mainwindow.c( the name of the label is click_test):
void data_labeling::on_label_clicked()
{
QString path="/home/j/Pictures/images.jpeg";
QPixmap cat(path);
connect(ui->click_test, SIGNAL(clicked()), this,
SLOT(on_label_clicked()));
ui->click_test->setPixmap(cat);
ui->click_test->resize(cat.width(),cat.height());
}
Of course I have promoted it to clicklabel.h and also I have added void on_label_click() to my mainwindow.h under private slots, but nothing happened.

Create a new class derived from QLabel, reimplement mousePressEvent to emit custom pressed() signal (or any other functionality you need)
If you need to use your clickable label in ui files, follow these steps:
Add QLabel to the form
Right-click on added label and select Promote to...
Enter your clickable label class name and its header file name
Press add, than select your label in the tree and select promote
Now you can use your subclassed label (this tutorial actually works for any subclassed widget) as any QWidget using ui->

You can use QPushButton instead, but if you desperately need QLabel, you can do this:
clickable.h
class Clickable :public QLabel
{
Q_OBJECT
signals:
void clicked();
public:
void mousePressEvent(QMouseEvent* event);
using QLabel::QLabel;
};
clickable.cpp
void Clickable::mousePressEvent(QMouseEvent* event)
{
emit clicked();
}
UPDATE:
This implementation I used in my source code. I can't paste complete code, but here is the part where I used it.
source.h
...
private:
QLabel* label1;
QLabel* label2;
...
source.cpp
...
label1 = new Clickable("label1 text", this);
label2 = new Clickable("label2 text", this);
...
connect(label1 , SIGNAL(clicked()), this, SLOT(label1clicked()));
connect(label2 , SIGNAL(clicked()), this, SLOT(label1clicked()));
...

Related

how to modify mainform.ui components from other form, and vice versa

how can i modify mainform.ui components(Qlabels, comboBox, etc ) from other form, and vice versa.
ex: 1-mainform.ui has a button(so called "button1"), when i click button1 i want to disable a button located in otherform.ui (so called "button2")
2- when i click on otherform.ui's button2, i want to clear a comboBox , located in mainform.ui
In ex #1 : i dont know how to reference otherform.ui, using the way> otherform obj;
obj.ui.button2.disabled(); the compiler show me a error!.
in ex#2: in the otherform.cpp i referencie the mainform.ui, creating an object type mainform,(mainform obj;), and then obj.ui.comboBox.clear();, when i run the app, an error said > mainform *ui is private, so i go to the mainform.h and make it public, then no signals of errors happen, but nothing happens.
someone can help me? excuse my english.
You can use the SIGNAL and SLOT mechanism to send mouse clicks from one form to another. The only requirement needed is that the forms, you are referring to, will have to be treated as 'Q_Object'.
Example
Form 1
#include <QObject> //must include this
class Form1 : public QObject
{
Q_OBJECT //must include this
public:
Form1(){ connect(&btn1, SIGNAL(clicked()), this, SLOT(clicked_btn1())); }
private:
QPushButton btn1;
public slots: /*slots are methods which are triggered when
signals are emitted */
void disable_btn(){btn1.disable();}
void clicked_btn1(){emit btn1_signal();}//signals are triggered by 'emit'
signals: /*signals are events waiting to be triggered*/
void btn1_signal();
};
Form 2
#include <QObject> //must include this
class Form2 : public QObject
{
Q_OBJECT //must include this
public:
Form2(){ connect(&btn2, SIGNAL(clicked()), this, SLOT(clicked_btn2())); }
private:
QPushButton btn2;
QComboBox cmb;
public slots: /*slots are methods which are triggered when
signals are emitted */
void clear_cmb(){cmb.clear();}
void clicked_btn2(){emit btn2_signal();}//signals are triggered by 'emit'
signals: /*signals are events waiting to be triggered*/
void btn2_signal();
;
};
Main
//include all the header files of form1 and form2
//include <QObject> file and Q_OBJECT
Form1 *form_1 = new Form1();
Form2 *form_2 = new Form2();
//connecting signals from one form to slots of another form
connect(form_1, SIGNAL(btn1_signal()), form_2, SLOT(disable_btn()))
connect(form_2, SIGNAL(btn2_signal()), form_1, SLOT(clear_cmb()))
So this is how a button from one object can be disabled from a click of a button inside another object.
Since this is a big topic, here's a link from Qt with more explanation and simple examples
http://doc.qt.io/archives/qt-4.8/signalsandslots.html

QWidget with doubleclick

I want to be able to double click a QPushbutton instead of a single click.
What I tried:
connect(pb, SIGNAL(doubleClicked()), this, SLOT(comBtnPressed()));
Error says "QObject::connect: No such signal QPushButton::doubleClicked()"
I chose QPushButton initially, but for my purpose, you can suggest change to other object if it can make a doubleclick event. Not necessarily be a push button.
Thank you Masters of Qt and C++.
A simple solution is to create our own widget so we overwrite the mouseDoubleClickEvent method, and you could overwrite paintEvent to draw the widget:
#ifndef DOUBLECLICKEDWIDGET_H
#define DOUBLECLICKEDWIDGET_H
#include <QWidget>
#include <QPainter>
class DoubleClickedWidget : public QWidget
{
Q_OBJECT
public:
explicit DoubleClickedWidget(QWidget *parent = nullptr):QWidget(parent){
setFixedSize(20, 20);
}
signals:
void doubleClicked();
protected:
void mouseDoubleClickEvent(QMouseEvent *){
emit doubleClicked();
}
void paintEvent(QPaintEvent *){
QPainter painter(this);
painter.fillRect(rect(), Qt::green);
}
};
#endif // DOUBLECLICKEDWIDGET_H
If you want to use it with Qt Designer you can promote as shown in the following link.
and then connect:
//new style
connect(ui->widget, &DoubleClickedWidget::doubleClicked, this, &MainWindow::onDoubleClicked);
//old style
connect(ui->widget, SIGNAL(doubleClicked), this, SLOT(onDoubleClicked));
In the following link there is an example.

Subclassing widgets in QT designer

I am having a hard time subclassing Widgets in the QDesigner. I am using QDesigner to create my UI, but using cmake to compile rather than .pro files. So I am basically using QT Creator for nothing other than generating ui files.
Now I want to subclass QLabel in order to override the mouse click event, so as far as I understand all I have to do is right click the QLabel and select "promote to". It then asks me what i want to promote to, so I say "clickable_qlabel.h". However, when I call "make", I get "ui_mainWindow.h:95:5: error: ‘Clickable_QLabel’ does not name a type". Unfortunately I have no idea where I need to put clickable_qlabel.h, or whether it already exists and I just need to fill it with my code.
Any help would be greatly appreciated!
Many thanks.
[UPDATE]
OK, so now I have created the following class:
QLabelClickable.h
#ifndef _QLABELCLICKABLE_H_
#define _QLABELCLICKABLE_H_
#include <QLabel>
#include <QMouseEvent>
class QLabelClickable : public QLabel
{
Q_OBJECT
public:
explicit QLabelClickable( const QString& text="", QWidget* parent=0 );
~QLabelClickable();
signals:
void clicked(int, int);
protected:
void mousePressEvent(QMouseEvent* event);
};
#endif
QLabelClickable.cpp
#include "QLabelClickable.h"
QLabelClickable::QLabelClickable(const QString& text, QWidget* parent)
: QLabel(parent)
{
setText(text);
}
QLabelClickable::~QLabelClickable()
{
}
void QLabelClickable::mousePressEvent(QMouseEvent* event)
{
emit clicked(event->x(),event->y());
}
So this code compiles beautifully. So now I am in QtDesigner and I create a QLabel, called label4, and I right click and select "Promote to". Then under "Promoted class name:" I type "QLabelClickable" and under "Header file:" I type "QLabelClickable.h". Then I click "Promote". Wonderful. But I am still getting the error:
Vigil/build/ui_mainWindow.h:328:42: error: no matching function for call to ‘QLabelClickable::QLabelClickable(QWidget*&)’ label_4 = new QLabelClickable(tab);
So clearly QtDesigner needs to be instructed (somehow) where my implementation of QLabelClickable is. Quite frustrating.
Eh. My error, I should have read the error message properly. I hadn't included a constructor for the passing of only a QWidget. Adding
QLabelClickable::QLabelClickable( QWidget* parent ) : QLabel(parent) {
}
to my CPP has solved the problem! Hooray.

Initializing a Ui pointer From a QMainWindow class to a QDialog Class

I'm really stuck on one problem that I want to solve. the problem is that I have a Class for QMainWindow which holds the Ui variable for that form. Now I want to be able to edit that Form using the Ui variable in that class on a QDialog cpp file. I probably sound really stupid and I really have no idea how I should explain this, but I have code which maybe can help.
MainWindow.h:
#include "ui_mainwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
Ui::MainWindow *ui;
}
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog.h"
Dialog *dialog;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
dialog = new Dialog(this);
dialog->show();
}
QDialog.cpp:
#include "ui_mainwindow.h"
#include "mainwindow.h"
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
}
Dialog::~Dialog()
{
delete ui;
}
Ui::MainWindow *mainui;
void Dialog::on_pushbutton_clicked(){
mainui->label->setText("test");
}
So as you can see from the above code, it shows that I have a pointer to the Ui variable however its uninitialised, therefore it would lead to a SIGSEGV error, so how to do Initialize this pointer? any help here is highly appreciated, and even though this is probably really simple I just don't know what to do. (I have looked at other questions but I couldn't quite grasp what to do, so please explain what I am to do before linking me to a similar question. Also, I have left out the Dialog.h file as I didn't think it was needed, please tell me if I need to show it, thanks!).
Generally in C++ you should practice what is called encapsulation - keep data inside a class hidden from others that don't need to know about it. It's not good to have multiple pointers to the UI object as now all those other objects have to know how the main window UI is implemented.
In this case, what I would recommend is to use Qt's signals and slots mechanism to allow the dialog to tell the main window what you need it to do. That has the advantage that if you add more dialogs, or change how things are implemented in the main window, you don't need to alter the signal slot mechanism, and the details are hidden cleanly.
So - for your dialog, add a signal like this in the header file
class Dialog : QDialog
{
Q_OBJECT
signals:
void setTextSignal(QString text);
}
and in your main window header, add a slot.
class MainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void setTextSlot(const QString &text);
}
now in your method where the button is pressed,
void Dialog::on_pushbutton_clicked()
{
emit setTextSignal("test");
}
and in your main window
void MainWindow::setTextSlot(const QString &text)
{
mainUi->label->setText(text);
}
The final part is to connect the signal and slot together, which you would do in your main window function where you create the dialog:
void MainWindow::on_pushButton_clicked()
{
dialog = new Dialog(this);
connect(dialog, SIGNAL(setTextSignal(QString)), this, SLOT(setTextSlot(QString)));
dialog->show();
}
You can see there are many advantages to this; the Dialog no longer needs a pointer to the main window UI, and it makes your code much more flexible (you can have other objects connected to the signals and slots as well).
Short answere - your can't! If you want to create a new instance of the ui, you would have to do:
MainWindow::Ui *ui = new MainWindow::UI();
ui->setupUi(this);
However, the this-pointer for a UI created for a QMainWindow based class must inherit QMainWindow - thus, you can't.
In general, it is possible if you create your Ui based on a QWidget instead of a QMainWindow, since both inherit QWidget.
Alternativly, you could try the following:
QMainWindow *subWindow = new QMainWindow(this);
subWindow->setWindowFlags(Qt::Widget);
MainWindow::Ui *ui = new MainWindow::UI();
ui->setupUi(subWindow );
//... add the mainwindow as a widget to some layout
But I would guess the result will look weird and may not even work in the first place.

Hiding/Showing DockWidgets in Qt 5 in Designer

I'm developing an application with Qt, a framework with which I'm not at all familiar, and I'm attempting to hide and show a DockWidget that I created using designer.
Unlike many of the seemingly similar questions about hiding and showing dockwidgets in Qt is that I made my widget entirely with Qt Designer, so I don't know how to link much of the code I've found in these questions' answers. Essentially, I have no mention of a dockwidget in my *.cpp files, but I do in my .ui file.
How can I incorporate this Designer-created dockwidget into my code to make it visible and invisible?
Sorry for such a nooby question.
Thanks,
erip
Wenn you build your application, qmake generates h from your ui files. So for instance ui_dlg_about.ui is translated into a ui_dlg_about.h automatically. Usually in a folder calles GeneratedFiles or something like that. You can then create an acutal customisable dialog class which you use in your application by creating something along the following:
dlg_about.h
#include "ui_dlg_about.h"
#include <QDialog>
class dlg_about : public QDialog, protected Ui::ui_dlg_about
{
Q_OBJECT
public:
dlg_about(QWidget* = 0);
public slots:
void toggle_dockwidget();
};
dlg_about.cpp
#include "dlg_about.h"
dlg_about::dlg_about(QWidget* parent) : QDialog(parent)
{
setupUi(this);
QObject::connect(this->somebutton, SIGNAL(clicked()), this, SLOT(toggle_dockwidget()));
}
void dlg_about::toggle_dockwidget()
{
if(something){
this->dockwidget->setVisible(true);
}else{
this->dockwidget->setVisible(false);
}
}
It is also possible for your dialog to not be derived from ui_dlg_about but having it as a member:
dlg_about.h
#include "ui_dlg_about.h"
#include <QDialog>
class dlg_about : public QDialog
{
Q_OBJECT
public:
dlg_about(QWidget* = 0);
public slots:
void toggle_dockwidget();
protected:
Ui::ui_dlg_about ui;
};
dlg_about.cpp
#include "dlg_about.h"
dlg_about::dlg_about(QWidget* parent) : QDialog(parent)
{
setupUi(this->ui);
QObject::connect(this->ui.somebutton, SIGNAL(clicked()), this, SLOT(toggle_dockwidget()));
}
....