I can't figure out how I can move a slider handle of a QSlider in QT. When I press for example A( I want to move coursor left) and D(I want move coursor right) so I did
(void) new QShortcut(Qt::Key_A, this, SLOT(moveTickmarkLeft()));
(void) new QShortcut(Qt::Key_D, this, SLOT(moveTickmarkRight()));
implementation:
void LCDRange::moveTickmarkLeft()
{
slider->setSliderPosition(slider->sliderPosition - 1);
}
void LCDRange::moveTickmarkRight()
{
slider->setSliderPosition(slider->sliderPosition + 1);
}
the same I did using function setTickPosition(), what is the difference between setSliderPosition() and setTickPosition() how can I implement my idea, thanx in advance for any help
I believe using setSliderPosition method is the correct way of moving your slider in code. setTickPosition set the way how the tick mark should be drawn, so I guess, this is not smth you need. As for intercepting keyboard events: you can install an event filter to your form ui controls and put your slider moving logic there. Below is an example. More details on event filter here
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// install event filter to ui controls of the window
ui->textEdit->installEventFilter(this);
ui->pushButton->installEventFilter(this);
ui->horizontalSlider->installEventFilter(this);
}
// event filter implementation
bool MainWindow::eventFilter(QObject* watched, QEvent* event)
{
if (event->type() == QEvent::KeyPress )
{
QKeyEvent* keyEvent = (QKeyEvent*)event;
if (keyEvent->key()=='A')
{
qDebug() << "move slider";
ui->horizontalSlider->setSliderPosition(ui->horizontalSlider->sliderPosition()+1);
}
else if (keyEvent->key()=='B')
{
qDebug() << "move slider";
ui->horizontalSlider->setSliderPosition(ui->horizontalSlider->sliderPosition()-1);
}
}
return QMainWindow::eventFilter(watched, event);
}
hope this helps, regards
Related
I am trying to create a menu app (like windows search) with QCompleter.
I would like to show all items from completer when the QLineEdit is empty.
And it works first time, but when I start typing something into the lineEdit and I delete all characters from lineEdit, and then press Enter I see nothing. Where is my mistake?
My code is below.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
this->wordList << "alpha" << "omega" << "omicron" << "zeta" << "icon";
this->lineEdit = new QLineEdit(this);
completer = new QCompleter(wordList, this);
completer->setCaseSensitivity(Qt::CaseInsensitive);
lineEdit->setCompleter(completer);
completer->QCompleter::complete();
ui->setupUi(this);
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter))
{
if(lineEdit->text()=="")
{
completer->complete();
}
if(wordList.contains(lineEdit->text(),Qt::CaseInsensitive))
qDebug() <<"CATCH IT";
}
}
Could you please advise me?
You need to reset the completion prefix on the completer.
if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
{
if(lineEdit->text().isEmpty())
{
lineEdit->completer()->setCompletionPrefix("");
lineEdit->completer()->complete();
}
}
Also if the intent is to only have it populate when return is pressed in the line edit, you will want to create your own line edit to handle that versus using the main window.
Just i've tested the following codes on QPushButton and on QWidget and i've encountered with different behaviors. But why?
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->widget->setStyleSheet("background:blue;");
ui->pushButton->setStyleSheet("background:blue;");
ui->widget->installEventFilter(this);
ui->pushButton->installEventFilter(this);
...
}
bool MainWindow::eventFilter(QObject* watched, QEvent* event)
{
if (watched==ui->pushButton && event->type()==QEvent::Paint)
{
// Do nothing
return true;
}
else if (watched==ui->widget && event->type()==QEvent::Paint)
{
// Do nothing
return true;
}
else
return QMainWindow::eventFilter(watched, event);
}
Then, the pushButton has disappeared as normally, because i've masked its paintEvent with eventFilter. But the widget has painted to blue. Why widget hasn't disappeared.
I've solved the problem with changing QEvent::Paint with QEvent::Polish.
To who wanted the detailed description
Thanks everybody.
I'm using QtCreator to build an interface application.
I'm just getting used to Qt and toying around trying to draw stuff on a QtGraphicsView.
Since I created my interface with the editor, I am retrieving my objects in the code like so (please tell me if this is wrong).
this->m_graphView = this->findChild<QGraphicsView *>("graphicsView");
this->m_graphScene = this->m_graphView->scene();
I have buttons on the interface and already created slots to react to the clicked event.
I'm just trying to draw something (anything) on the graphics view that is on my MainWindow (geometry : [(10,10), 320x240]).
I've been reading examples online and I can't make anything work.
My current code is as follows :
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->m_graphView = this->findChild<QGraphicsView *>("graphicsView");
this->m_graphScene = this->m_graphView->scene();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnDown_clicked()
{
qDebug() << "STUB : button DOWN";
m_graphScene->addLine(0, 0, 42, 42, QPen(QBrush(Qt::black),1));
m_graphView->show();
}
void MainWindow::on_btnLeft_clicked()
{
qDebug() << "STUB : button LEFT";
}
void MainWindow::on_btnUp_clicked()
{
qDebug() << "STUB : button UP";
}
void MainWindow::on_btnRight_clicked()
{
qDebug() << "STUB : button RIGHT";
}
void MainWindow::on_btnShoot_clicked()
{
qDebug() << "STUB : button SHOOT";
}
But annoyingly, it doesn't draw anything and I even get this error when the addLine method is called
QGraphicsScene::addItem: item has already been added to this scene
What's wrong in my code and/or my ways of doing things?
I just want to draw something but can't make it, thank you.
retrieving widget in form
you can get graphicsView pointer (and its scene) more easier.
"ui" member has the pointer to widgets arranged in .form file.
(If you please, see "ui_mainwindow.h" file)
// assign to pointer
QGraphicsView *view = ui->graphicsView;
view->...
// or directly (I like this)
ui->graphicsView->...
so, Mainwindow class don't need "m_graphicsView" member.
graphics view
QGraphicsView need to set scene.(It has no scene at first)
We have to create QGraphicsScene ourselves.
So Mainwindow class need "m_graphicsScene" member.
m_graphicsScene = new QGraphicsScene(this);
ui->graphicsView->setScene(m_graphicsScene);
drawing more easier
If you just want to draw something, you can override "paintEvent" method.
PaintEvent is QWidget's virtual method.
in .h file:
protected:
void paintEvent(QPaintEvent *event);
in .cpp file:
void MainWindow::paintEvent(QPaintEvent *event)
{
// unuse
Q_UNUSED(event);
// pass "this" pointer to painter
QPainter painter(this);
// setPen
// QPen can take "Qt::black" directly as first arg (without QBrush() constructor)
painter.setPen(QPen(Qt::black), 1);
// draw line
painter.drawLine(0, 0, 42, 42);
}
please enjoy Qt!
I'm trying to get a QDateEdit to allow the QCalendarWidget to show when requested (rather than just on clicking the down arrow). For example, somewhere in my class I should be able to say:
ui.datepicker.showCalendar()
and it should load up the calendar that appears right below the date picker.
It looks like I need to sub-class QDateEdit, as this doesn't work:
QDateEdit *de = new QDateEdit();
de->calendarWidget()->show();
I've also tried sending keyboard commands as dictated when you go through the QDateTimeEdit.cpp source for Qt, but seems my keyboard shortcuts are disabled or something.
Any ideas on what I have to do to sub-class to get this to work? I was thinking of something like:
class MyDateEdit : QDateEdit
{
Q_OBJECT
protected:
void mouseEvent(QEvent *event) {
this.calendarWidget().show();
}
};
But alas that also doesn't seem to compile in or work correctly.
Enable "setCalendarPopup ( bool enable )" in QDateTimeEdit allows to popup the calendar
I was able to figure it out on my own - still no sure how to get QDateEdit to work properly, but I used a QLineEdit and it suited my needs. Just connect QCalendarWidget's "onClick(QDate)" to a slot you create that does a:
setText(date.toString("M/d/yyyy"));
ui->calendar->hide();
Then add an event filter to the QLineEdit using the "OnFocusIn" event that does a "ui->calendar->show();" See: Get a notification/event/signal when a Qt widget gets focus
#Rob S answer
You were right with event filter approach we would do same with QDateEdit.
I am writing the code which extends your approach with QDateEdit :
In mainwindow.h I created a QCalendar pointer (Using QtCreator)
Following is the code of mainwindow.cpp (I am giving out fullcode so that rookies like me can benifit from it)
Make sure you set buttonSymbol and calendarpopup property to false to make it work correctly
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCalendarWidget>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->dateEdit->setDate(QDate::currentDate());
widget=new QCalendarWidget(); //widget is QCalendar pointer
ui->verticalLayout->addWidget(widget);
widget->setWindowFlags(Qt::Popup); // we need widget to popup
ui->dateEdit->installEventFilter(this);
connect(widget,SIGNAL(clicked(QDate)),ui->dateEdit,SLOT(setDate(QDate)));
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::InputMethodQuery)
{
if (object == ui->dateEdit)
{
if(widget->isVisible()==false && ui->dateEdit->calendarWidget()->isVisible()==false) // this done to avoid conflict
{
qWarning(QString().number(event->type()).toStdString().c_str());
qWarning(object->objectName().toLatin1().data());
widget->move(ui->dateEdit->mapToGlobal(QPoint(0,ui->dateEdit->height())));
widget->show();
}
}
}
return false;
}
OR :: Alternatively we can use QCalendarWidget provided by dateEdit, though its not much efficient as turing it to Popup will mess with its internal. Give it a shot if you want
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCompleter>
#include <QCalendarWidget>
#include <QMouseEvent>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->dateEdit->setDate(QDate::currentDate());
widget = ui->dateEdit->calendarWidget();
widget->setWindowFlags(Qt::Popup);
ui->dateEdit->installEventFilter(this);
//connecting widget with dateedit
ui->dateEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
ui->dateEdit->setCalendarPopup(true);
connect(widget,SIGNAL(clicked(QDate)),ui->dateEdit,SLOT(setDate(QDate)));
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->dateEdit)
{
if (event->type() == QEvent::FocusIn || event->type() == QEvent::MouseButtonPress)
{
// WE NEED MOUSE EVENT TO AVOID INTERFERNCE WITH CALENDAR POPUP BUTTON SITUATED AT CORNER OF dateEdit WIDGET
if(widget->isVisible()==false && ( ((QMouseEvent* )event)->x()< (ui->dateEdit->width()-10)))
{
widget->move(ui->dateEdit->mapToGlobal(QPoint(0,ui->dateEdit->height())));
widget->show();
}
}
}
return false;
}
I'd like to offer option similar to #Dr. Xperience's answer that encapsulates calendar widget in QDateEdit subclass:
#include <QDateEdit>
#include <QCalendarWidget>
class DateEdit : public QDateEdit {
Q_OBJECT
public:
explicit DateEdit(QWidget *parent = nullptr);
protected:
virtual void focusInEvent(QFocusEvent *event) override;
private:
QCalendarWidget *calendar = new QCalendarWidget(this);
};
DateEdit::DateEdit(QWidget *parent) : QDateEdit (parent) {
setButtonSymbols(QAbstractSpinBox::NoButtons);
setCalendarPopup(false);
setDate(QDate::currentDate());
calendar->setWindowFlags(Qt::Popup);
connect(calendar, &QCalendarWidget::clicked, this, [&](const QDate &date) {
setDate(date);
calendar->hide();
});
}
void DateEdit::focusInEvent(QFocusEvent *event) {
if (!calendar->isVisible()) {
calendar->setSelectedDate(date());
calendar->move(mapToGlobal(QPoint(0, height())));
calendar->show();
}
return QDateEdit::focusInEvent(event);
}
Warning: If you place this widget using QtDesigner, it will override buttonSymbols and calendarPopup properties, so you have to set it manually to hide QDateEdit's buttons.
Here is my hacky approach to the issue. After fighting for quite a while to have something clean, I read the source code of QDateEditor (which in fact is just a simplified QDateTimeEditor) and it seems to be no clean solution. The following is code for toggle() rather than show(), but still:
// Enable the calendar popup
date_editor->setCalendarPopup(true);
// Show the calendar popup by default
// There seems to be no proper interface to achieve that
// Fake a mouse click on the right-hand-side button
QPointF point = date_editor->rect().bottomRight() - QPointF{5, 5};
QCoreApplication::postEvent(
date_editor,
new QMouseEvent(QEvent::MouseButtonPress, point, Qt::LeftButton,
Qt::LeftButton, Qt::NoModifier));
Using something like this you can keep relying on the editor's validation features.
BTW, another annoying thing about the built-in editor that makes a QLineEdit tempting is that (at least in my case) the keyboard cursor is not shown by default. This is very confusing. To solve this I did:
// Select a section so that the cursor is be visible
date_editor->setSelectedSection(QDateTimeEdit::DaySection);
This or course selects the day section of the date, but if you use keyboard arrows the selection vanished, but you can see the keyboard cursor.
I have a console input in my Qt based application, it's a QLineEdit, all Ui is designed via QtDesigner. Is it any easy way way to handle up and down arrows in order to implement input history? The 'go to slot' only show returnProcessed signal, no way i can see to handle up and down arrows :(
you can install event filter and watch your line edit event in your window class. Below is an example:
declare event handler method on your window class:
class MainWindow : public QMainWindow {
Q_OBJECT
...
protected:
void changeEvent(QEvent *e);
...
};
window constructor
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
...
ui->lineEdit->installEventFilter(this);
}
event handler implementation:
bool MainWindow::eventFilter(QObject* obj, QEvent *event)
{
if (obj == ui->lineEdit)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Up)
{
qDebug() << "lineEdit -> Qt::Key_Up";
return true;
}
else if(keyEvent->key() == Qt::Key_Down)
{
qDebug() << "lineEdit -> Qt::Key_Down";
return true;
}
}
return false;
}
return QMainWindow::eventFilter(obj, event);
}
hope this helps, regards
You can subclass QLineEdit and re-implement the virtual keyPressEvent method to handle your special keys.
void MyLineEdit::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Up){
// move back in history
}
else if(event->key() == Qt::Key_Down){
// move forward in history
}
else{
// default handler for event
QLineEdit::keyPressEvent(event);
}
}
I had the same problem, but I find out in other forums that you need to setFocus, e.g.:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
...
ui->lineEdit->installEventFilter(this);
this->setFocus();
}
It works for me.
Reference:
http://www.qtforum.org/article/28240/how-to-get-arrow-keys.html
For me in PyQt this was not working,
class MainWidget(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setupUi()
self->installEventFilter(self)
But this worked,
class MainWidget(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setupUi()
QtGui.QApplication.instance().installEventFilter(self)