Repositioning a label with mouseevents to anywhere on the screen - c++

I've created a label and used setPixmap to attach a .png image to the label. I've also setWindowFlags to disable the title bar and create a frameless window. Because I've disabled those, it also disables the ability to drag anything around, so I want to create mouseevents (unless there's a better method) to position my label anywhere on the screen exactly like dragging the frame of a window. How would I do that? An example and brief explanation would be greatly appreciated.

reimplement the QMouseEvents you need .... like
void MyLabel::mousePressEvent(QMouseEvent* e)
{
m_moveDatWidget = true;
// so when the mousebutton got pressed, you set something to
// tell your code to move the widget ... consider maybe you
// want to move it only on right button pressed ...
}
void MyLabel::mouseReleaseEvent(QMouseEvent* e)
{
m_moveDatWidget = false;
// after releasing do not forget to reset the movement variable
}
void MyLabel::mouseMoveEvent(QMouseEvent* e)
{
// when in 'moving state' ...
if (m_moveDatWidget)
{
// move your widget around using QWidget::move(qreal,qreal)
}
}
this is only a really basic implementation but it should do well if you calculate the desired movement correct :)

I would implement the label dragging by mouse in the following way:
class Label : public QLabel
{
public:
// Implement the constructor(s)
protected:
void Label::mouseMoveEvent(QMouseEvent* event)
{
if (!m_offset.isNull()) {
move(event->globalPos() - m_offset);
}
QLabel::mouseMoveEvent(event);
}
void Label::mousePressEvent(QMouseEvent* event)
{
// Get the mouse offset in the label's coordinates system.
m_offset = event->globalPos() - pos();
QLabel::mousePressEvent(event);
}
void Notifier::mouseReleaseEvent(QMouseEvent* event)
{
m_offset = QPoint();
QLabel::mouseReleaseEvent(event);
}
private:
// The mouse pointer offset from the top left corner of the label.
QPoint m_offset;
};

Related

How to display some text besides mouse pointer when the mouse hover over QGraphicsItem's in Qt?

I have a QGraphicsView, which contains many rectangle and polylines. I wanted to print every object names ( every rectangle, polylines have names) once I clicked them on view through mouse click. I did that and worked perfectly.
But now I want to do that over mouse hovering. It means, if I hover a mouse over particular object, it should show its name besides cursor.
I tried that, but
I am not understanding, on hovering, how that particular object should get selected ?
And how to print its name besides cursor point ?
I tried this way:
bool myClass::eventFilter(QObject *watched, QEvent *event)
{
bool filterEvent = false;
switch(event->type())
{
case QEvent::MouseButtonPress:
{....}
case QEvent::MouseButtonRelease:
{...}
case QEvent::Enter:
{
QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
QPointF po = _view->mapToScene(mouseEvent->pos());
FindNamesOverHover(po);
}
return true;
default:
break;
}
return filterEvent;
}
void myClass::FindNamesOverHover(QPointF p)
{
QGraphicsRectItem* rItem = qgraphicsitem_cast<QGraphicsRectItem*>(_scene->itemAt(p,QTransform()));
if(rItem)
{
// some logic
qDebug()<< "Instance name is " << i->Name();
}
}
Constructor of class myClass
myClass::myClass(QWidget* parent) :
QDockWidget(parent)
{
scene = new QGraphicsScene(this);
view = new QGraphicsView(this);
view->setScene(_scene);
view->viewport()->installEventFilter(this);
}
Now above code works only,
When I select object through mouse click and then again hover over it.
Then it prints its name on console.
But I want only hovering ( no selection through mouse click) will show its name besides cursor point.
Can any one help me ?
You can override QGraphicsScene.mouseMoveEvent and inside it use QGraphicsScene.itemAt to query for item under cursor. To display you can use QGraphicsTextItem, just move it to correct position and apply text.

How drag and drop qwidget consisting of several widgets?

I have a several QWidgets, let's say previewWidget, that each consist of 2 QLabels (maybe more and other than QLabel). I want to drag and drop previewWidgets across the main window.
Problem: I can move the widget by pressing the mouse on the green area, which is PreviewWidget area. However, if I try to drag the widget by clicking on one of the labels, that label moves out the previewWidget (sometimes I don't even understand what happens). What I want is to move a whole previewWidget or at least nothing to happen when a mouse is pressed on its children.
My approach. I overloaded mousePressEvent() as follows:
void MainWindow::mousePressEvent(QMouseEvent *event)
{
// I beleive my problem is right here...
PreviewWidget *child = static_cast<PreviewWidget*>(this->childAt(event->pos()));
if (!child)
return; // this is not returned even if the child is not of a PreviewWidget type
// Create QDrag object ...
}
How to drag and drop PreviewWidget the way I want? Any examples are appreciated.
I suggest a strategy for identifying the child at the cursor coordinates.
In your mousePressEvent:
//...
QWidget * child = childAt(e->pos());
if(child != 0)
{
QString classname(child->metaObject()->className());
if( classname == "QLabel")
{
child = child->parentWidget();
if(child != 0)
{
classname = child->metaObject()->className();
}
}
if(classname == "PreviewWidget")
{
//do whatever with child ...
}
}

Remove scroll functionality on mouse wheel QGraphics view

I have a QGraphicsView window on my widget and have just put in an event for mouse wheel which zooms in on the image.
However as soon as i zoom in scroll bars are displayed and the scroll functionality on the mouse wheel overrides the zoom function i have.
i was wondering if there is any way that i can remove scrolling all together and add a drag to move option or maybe a CTRL and mouse wheel to zoom and mouse wheel alone would control scrolling
here is my zoom function (Which im aware isnt perfect) but if anyone could shed some light on that it would be a bonus
cheers in advance
void Test::wheelEvent(QWheelEvent *event)
{
if(event->delta() > 0)
{
ui->graphicsView->scale(2,2);
}
else
{
ui->graphicsView->scale(0.5,0.5);
}
}
You reimplemented wheelEvent for QWidget/QMainWindow that contains your QGraphicsView, however, wheelEvent of QGraphicsView remains intact.
You can derive from QGraphicsView, reimplement wheelEvent for derived class and use derive class instead of QGraphicsView - this way you won't even need wheelEvent in your QWidget/QMainWindow, and you can customize reimplemented wheelEvent to do what you want. Something like that:
Header file:
class myQGraphicsView : public QGraphicsView
{
public:
myQGraphicsView(QWidget * parent = nullptr);
myQGraphicsView(QGraphicsScene * scene, QWidget * parent = nullptr);
protected:
virtual void wheelEvent(QWheelEvent * event);
};
Source file:
myQGraphicsView::myQGraphicsView(QWidget * parent)
: QGraphicsView(parent) {}
myQGraphicsView::myQGraphicsView(QGraphicsScene * scene, QWidget * parent)
: QGraphicsView(scene, parent) {}
void myQGraphicsView::wheelEvent(QWheelEvent * event)
{
// your functionality, for example:
// if ctrl pressed, use original functionality
if (event->modifiers() & Qt::ControlModifier)
{
QGraphicsView::wheelEvent(event);
}
// otherwise, do yours
else
{
if (event->delta() > 0)
{
scale(2, 2);
}
else
{
scale(0.5, 0.5);
}
}
}
Scrolling can be disabled with the following code:
ui->graphicsView->verticalScrollBar()->blockSignals(true);
ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->graphicsView->horizontalScrollBar()->blockSignals(true);
ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
I think your question has a bit simpler answer.. To disable scroll bars just set scroll bar policy (QGraphicsView is just QScrollView), so step 1)
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
that will disable scroll bars..
step 2) (if you want to keep it simple)
QGraphicsView * pView; // pointer to your graphics view
pView->setInteractive(true);
pView->setDragMode(QGraphicsView::ScrollHandDrag);
thats the fastest way to get results you want

Select & moving Qwidget in the screen

I'm using QTCreator and I created a QWidget, then I have hidden the title bar with setWindowFlags(Qt::CustomizeWindowHint);.
But I can't select or move my widget. How can I use the mouseEvent to solve that?
If you want to be able to move your window around on your screen by just clicking and dragging (while maintaining the mouse button pressed), here's an easy way to do that:
#include <QtGui>
class W: public QWidget
{
Q_OBJECT
public:
explicit W(QWidget *parent=0) : QWidget(parent) { }
protected:
void mousePressEvent(QMouseEvent *evt)
{
oldPos = evt->globalPos();
}
void mouseMoveEvent(QMouseEvent *evt)
{
const QPoint delta = evt->globalPos() - oldPos;
move(x()+delta.x(), y()+delta.y());
oldPos = evt->globalPos();
}
private:
QPoint oldPos;
};
In mousePressEvent, you save the global (screen-coordinate) position of where the mouse was, and then in the mouseMoveEvent, you calculate how far the mouse moved and update the widget's position by that amount.
Note that if you have enabled mouse tracking, you'll need to add more logic to only move the window when a mouse button is actually pressed. (With mouse tracking disabled, which is the default, mouseMoveEvents are only generated when a button is held down).

How can I add a button to the corner of a widget in QT?

I am trying to display a square image and have an X in the top right corner (half in the image half outside) to close the image. I dont know of a layout manager that will allow me to do that. How do I implement this?
+---------O <- close button
| |
| |
+---------+
There will be a lot to implement here. I've accomplished this in the following way:
Step 1. Subclass QLabel to make it possible to capture mouse clicks. In the header declare signals Clicked and Pressed, and override the proper mouse events.
LabelButton::LabelButton(QWidget *parent) : QLabel(parent)
{
}
void LabelButton::mouseReleaseEvent(QMouseEvent *event){
emit Clicked();
event->accept();
}
void LabelButton::mousePressEvent(QMouseEvent *event){
emit Pressed();
event->accept();
}
Step 2. Add a LabelButton called xbutton containing an circular 'x' image to your widget at the location that you desire.
Example (This would be in your setupUi function):
...
xbutton = new LabelButton(MainWidget);
xbutton->setObjectName(QString::fromUtf8("xbutton"));
xbutton->setGeometry(QRect(0, 0, 31, 31));
xbutton->setPixmap(QPixmap(QString::fromUtf8(":/xbutton.gif")));
xbutton->setAlignment(Qt::AlignCenter);
...
Step 3. Create your widget. Set its background to transparent, and make sure its size includes room for the 'x' close button. Note: Setting your background to transparent means your widget will have to contain some child widget that accepts input from the user.
Example:
mywidget::mywidget(QWidget *parent): QWidget(parent){
setupUi(this);
moving=false; // notice that you must declare this bool for Step 4.
offset=QPoint(0,0); // Also a QPoint for Step 4
#if defined(Q_WS_MAC) //These values worked for me with the Mac OS 10.5 SDK
this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | Qt::Window);
QPalette pal = this->palette();
pal.setColor(this->backgroundRole(), Qt::transparent);
this->setPalette(pal);
#elif defined(Q_WS_WIN)//These values worked for me on Windows XP/Vista/7
this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |Qt::FramelessWindowHint | Qt::Window);
setStyleSheet("background:transparent;");
setAttribute(Qt::WA_TranslucentBackground);
#endif
connect(xbutton,SIGNAL(Clicked()),this,SLOT(hide()));
}
Now you have the functionality that you originally desired. When you click the xbutton, the window will close. But you will not have normal move functionality until you implement that.
Step 4. Implement move functionality to your widget.
/*
FUNCTION:mousePressEvent
used to help move the widget since there is no title bar, sets the initial offset of the mouse
*/
void mywidget::mousePressEvent(QMouseEvent *event){
if((event->button() == Qt::LeftButton)) {
moving = true;
offset = event->globalPos() - this->pos();
}
}
/*
FUNCTION:mouseReleaseEvent
used to help move the widget since there is no title bar, releases the "moving" attribute
*/
void mywidget::mouseReleaseEvent(QMouseEvent *event){
if(event->button() == Qt::LeftButton) {
moving = false;
}
}
/*
FUNCTION:mouseMoveEvent
used to help move the widget since there is no title bar
*/
void mywidget::mouseMoveEvent(QMouseEvent *event){
if(moving){
QPoint global = event->globalPos();
this->setGeometry(global.x()-offset.x(),global.y()-offset.y(),this->width(),this->height());
}
}
I found this way to be of most use to me, because I needed lots of functionality out of my customized slick-looking widget.
I really enjoy creative user interfaces and I hope that yours looks really sleek when you get it finished!