Currently i am learning Qt in C++ and have following issue:
Connecting "textChanged" or "textEdited" with a slot does not work.
Header file:
#include ...
class PersonalPreferences : public QWidget
{
Q_OBJECT
public:
PersonalPreferences(QWidget *parent = nullptr);
public slots:
void make_available();
private:
...
};
Code file:
PersonalPreferences::PersonalPreferences(QWidget *parent) {
// Configuring Layout
connect(line_edit_name, SIGNAL(textEdited()), this, SLOT(make_available()));
}
make_available function:
void PersonalPreferences::make_available() {
label_name->setText("wadwad");
group_box_pref->setEnabled(true);
push_button_ok->setEnabled(true);
push_button_close->setEnabled(true);
}
Please notice that i intentionally reduced the code to it's significant parts and didn't include the main file. I tried the same code with and without the parameter make_available(const QString &text). Yet it does not change the outcome.
I also tried this
connect(line_edit_name, &QLineEdit::textEdited, this, &PersonalPreferences::make_available);
and still it did not work out.
I noticed that using QTextEdit instead of QLineEdit works, but nevertheless i need help to solve this issue with QLineEdit.
Thanks in advance!
you need to study the details carefully)
In QLineEdit, the signal is
void textChanged ()
In QTextEdit, the signal is
void textChanged (const QString & text)
then you need to make such an amendment
void make_available()
change to
void make_available(const QString & text)
and call
connect(line_edit_name, &QLineEdit::textEdited, this, &PersonalPreferences::make_available);
or
connect(line_edit_name, SIGNAL(textEdited()), this, SLOT(make_available()));
change to
connect(line_edit_name, SIGNAL(textEdited(QString)), this, SLOT(make_available(QString)));
Related
I am trying to use QTest to test UI interactions with a QListWidget.
Interactions made from a simple click work fine (QTest::mouseClick()) but interactions from a double click do not (QTest::mouseDClick()).
Here is simplified code sample to reproduce the issue :
Dialog.h
class UILIBSHARED_EXPORT Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
int doubleClickCount = 0;
QString lastItemClicked = "";
QListWidget* GetListW();
private slots:
void on_listWidget_doubleClicked(const QModelIndex &index);
public:
Ui::Dialog *ui;
};
Dialog.cpp
QListWidget*Dialog::GetListW()
{
return ui->listWidget;
}
void Dialog::on_listWidget_doubleClicked(const QModelIndex &index)
{
lastItemClicked = ui->listWidget->item(index.row())->text();
++doubleClickCount;
}
And the test class :
class DoubleClickTest : public QObject
{
Q_OBJECT
public:
DoubleClickTest();
private Q_SLOTS:
void testDoubleClick();
};
void DoubleClickTest::testDoubleClick()
{
Dialog dialog;
dialog.show();
QListWidgetItem* item = dialog.GetListW()->item(1);
QRect rect = dialog.GetListW()->visualItemRect(item);
QTest::mouseDClick(dialog.GetListW()->viewport(), Qt::LeftButton, Qt::KeyboardModifiers(), rect.center());
QCOMPARE(dialog.doubleClickCount, 1);
}
I checked the dialog manually and the slot is called as expected.
I know this is an old topic but I have encountered the same behaviour with a QTreeView and have passed some hours to find a workaround, so I think it can be useful for someone else.
Using QTest, the signal doubleClicked is never emitted due to a part of code in sources of Qt I do not understand (qtreeview.cpp, line 1934 with Qt 5.12.1, or for others, in qabstractitemview.cpp line 1952). I don't know if it is a bug or not.
To avoid this strange code, I just added a call to QTest::mouseClick before the call to QTest::mouseDClick with the same parameters.
It worked for me because my QTreeView do nothing particular on a simple click, but it can distort tests in another case.
If anyone has a better solution I take it !
I'm pretty new to the Model and View concept and I'm having trouble finding the right way to do this. So in my understanding the concept means, that I have one class that handles all the view (GUI) parts and an other class which handles the data processing.
The GUI I made has a few Display Widgets (LCDnumbers) which just have to get data from the other class and output it into the LCD.
So I made a function in the GUI class which can set a number into the LCD. And I've made a function which can change the value of the number in the data class.
Now I need something to connect those, for example when I change the number in the data class I want it to update in the GUI. I found somethings about Signals and Slots (and emitting a signal) but how does that work, while maintaining the Model and View concept?
It could be that this is answered somewhere else, if so, can you link me the source? I couldn't find anything to solve my problem.
Thanks for reading and I hope someone can help me.
Header file of the GUI:
#include <QMainWindow>
#include <QtCore>
namespace Ui {
class MainBoardView;
}
class MainBoardView : public QMainWindow
{
Q_OBJECT
public:
explicit MainBoardView(QWidget *parent = 0);
~MainBoardView();
void ChangeNumber(int value);
private:
Ui::MainBoardView *ui;
};
CPP file of the GUI:
#include "mainboardview.h"
#include "ui_mainboardview.h"
MainBoardView::MainBoardView(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainBoardView)
{
ui->setupUi(this);
}
MainBoardView::~MainBoardView()
{
delete ui;
}
void MainBoardView::ChangeNumber(int value)
{
ui->lcdNumber->display(value);
}
Code of the data class:
Header:
class MainBoard
{
public:
MainBoard();
void changeMoney(int value);
private:
int m_money;
}
CPP:
void MainBoard::ChangeMoney(int value)
{
m_money = value;
//emit a signal here with the value to the ChangeNumber function of the GUI?
//and how should I do this?
}
For applying model/view concept of Qt you should use at least one of a model classes. Such model classes provide unified interface for several types of data (string-list, trees, sql, etc.)
For displaying the data one would use either a view-class or widgets connected to the model via QDataWidgetMaper
In your case there is no use of model/view observable. MainBoard should be QObject for emitting the signal:
class MainBoard: public QObject
{
Q_OBJECT
public:
MainBoard();
void changeMoney(int value); //emit value with emit moneyChanged(value) in the implementation.
signals:
void moneyChanged(int)
private:
int m_money;
}
I am new to QT. I have been trying to see the bridge between javascript and Qt Class.
What I did:
1) I have a button and connected clicked signal to on_pushButton_clicked, also I have qwebview instance.
In on_pushButton_clicked:
...
QUrl url = QUrl::fromLocalFile("C:\\whoami\\sd\\index.html");
QObject::connect(ui->webView->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
this, SLOT(addJSObject()));
ui->webView->page()->mainFrame()->load(QUrl(url));
....
and in addJSObject,
void MainWindow::addJSObject()
{
qDebug () <<"Inside addJSObject";
ui->webView->page()->mainFrame()->addToJavaScriptWindowObject(QString("mBridge"), m_bridge);
qDebug () <<"Nooo. I m not invoked..";
}
Problem:
It compiles without error, and html file is displayed in the qwebview, but addJSObject callback is not invoked.
Could someone help me in order to resolve this issue?.. I must have done some silly mistake. :(.
Make sure, that your MainWindow: 1) inherits QObject 2) has Q_OBJECT macro 3) has a slot addJSObject().
For example mainwindow.h:
class MainWindow : public QObject
{
Q_OBJECT
public:
MainWindow();
private slots:
void addJSObject();
};
If this is correct, you should be able to connect to addJSObject() without static QObject::connect(). Just use connect() when referring to this as signal target object.
One way to just check, that your signalling works is to try using QTimer timeout signal:
QTimer::singleShot(5000, this, SLOT(addJSObject()));
I have a QTableView to display a bunch of data, which is stored in a QAbstractTableModel. I also want to edit the data sometime, so I use a QStyledItemDelegate to create an editor (of QTextEdit type) when I double click on the cell. However, I want to handle the key Press event myself, but I never catch Key_Escape pressing in the Text Edit editor (Other keys such as Enter and Ascii can be captured). I checked the code, and found that Escape is directly connected to QTableView's closeEditor() function, which is a virtual method and is automatically invoked. As far as I know, key press event is the bottom layer of event handling, but it is not true with such case.
I do need to capture the Escape key press event so that I can handle it myself, can anyone tell me how to do this? Thanks!
I got the answer, and I think would help others:
Override QStyledItemDelegate::eventFilter() method:
MyItemDelegate::eventFilter(QObject* editor, QEvent* event)
{
if(event->type()==QEvent::KeyPress)
return false;
return QStyledItemDelegate::eventFilter(editor, event);
}
According to Qt's documentation, QStyledItemDelegate::eventFilter() returns true if the given editor is a valid QWidget and the given event is handled; otherwise returns false. Tab, Backtab, Enter, Return and Ecs are handled by default. So, if you want to handle the key press event yourself, you must let eventFilter return false when KeyPress event occurs. So that the editor's keyPressEvent() method will be invoked instead.
QStyledItemDelegate::eventFilter is not a possibility beacuse is virtual protected
In order to get the events you should subclass your own QEditLine and override ::keyPressEvent there. Take notice of the code. I pass actual row and colum of my QTableWidget cell in order to know what we are editing in the overrided QLineEditor.
//.h
class MyStyledItemDelegate : public QStyledItemDelegate
{
public:
MyStyledItemDelegate(QObject *parent = 0);
QWidget* createEditor(QWidget* parent,const QStyleOptionViewItem &option,const QModelIndex &index) const;
};
//.cpp
#include "mylineedit.h"
MyStyledItemDelegate::MyStyledItemDelegate(QObject *parent)
:QStyledItemDelegate(parent)
{
}
QWidget* MyStyledItemDelegate::createEditor(QWidget* parent,const QStyleOptionViewItem &option,const QModelIndex &index) const
{
MyLineEdit* editor = new MyLineEdit(parent,index.row(),index.column());
return editor;
}
/////////////////////////////////////////////////////////////
//My own QLineEdit
/////////////////////////////////////////////////////////////
//.h
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
int _nRow;
int _nCol;
public:
MyLineEdit(QWidget *parent = 0,int nRow=-1, int nCol=-1);
virtual void keyPressEvent(QKeyEvent* event);
signals:
void mySignal(const QVector<QVariant> &);
public slots:
};
//.cpp
MyLineEdit::MyLineEdit(QWidget *parent, int nRow,int nCol):
QLineEdit(parent)
{
_nRow=nRow;
_nCol=nCol;
}
/////////////////////////////////////////////////////////////////////////
void MyLineEdit::keyPressEvent(QKeyEvent* event)
{
qDebug() << "MyLineEdit::OnKeyPressEvent:"<<event->text()<< " row="<<_nRow<<" col=" <<_nCol;
///SET YOUR CODE HERE
QLineEdit::keyPressEvent(event);
}
I'm using Phonon::SeekSlider, it's a cool thing and I don't need to bother about synchronization between slider and MediaObject but now I need to track the moment when user releases the slider after moving it or when it's value is changed or when the current time of MediaObject is changed. I cannot find any public signals, I can see them in the slider's code but they are private. How could I inherit/implement/track whatever to track this event?
Thanks
You can create a class inherits SeekSlider
in the .h file :
#include <Phonon/SeekSlider>
using namespace Phonon;
class MySeekSlider : public SeekSlider
{
Q_OBJECT
public:
MySeekSlider(QWidget *parent = 0);
signals:
void release(qint64 pos);
protected:
virtual void mouseReleaseEvent(QMouseEvent *);
};
and in the.cpp
void MySeekSlider::mouseReleaseEvent(QMouseEvent *)
{
emit release(this->pos());
}
or use the tick signal of your MediaObject
void tick ( qint64 time )
You may connect to private signals same way as to any others.
QStaticMetaObject ignores visibility level of signals|slots. The only difference of private signals from normal (which has protected visibility level) - you cannot emit them when subclassing your Phonon::SeekSlider.
I suppose there is no way to do it but to create a new class inherited from QSlider, and add the whole functionality about MediaObject inside.