Creating a Pixmap for drag and drop
Hello,
I would like to drag and drop QFrames around in my own application and I'm wondering if there is a generic way to construct the Pixmaps of the QFrames that are shown when the frame is being dragged. From what I saw so far the Pixmaps are always constructed by hand. Can't I do something like using the QFrame's already existing paintEvent() method to have it paint on a QImage instead and then convert the QImage to a QPixmap? Because then I figure the Pixmap would look just like the frame appears on the screen and that's exactly what I need.
Thanks
Cruz
Re: Creating a Pixmap for drag and drop
what do you need a screenshot of QFrame? if yes, then take a look at QPixmap QPixmap::grabWidget ( QWidget * widget, int x = 0, int y = 0, int width = -1, int height = -1 )
Re: Creating a Pixmap for drag and drop
It's not really a screenshot what I want. When you drag something over the screen a pixmap is displayed that moves along with the cursor. When I drag a frame, I want this pixmap to show the very same frame. Just like in the puzzle and the fridgemagnets example. Or when you drag an image in Firefox, you see the very same image just a bit blurred and transparent. It's a really cool effect. And now instead of constructing a pixmap for every kind of draggable widget I have, I would like to find a generic way to construct it. So I guess your suggestion is good! Even if you call it a screenshot. :) I will look into it shortly.
Re: Creating a Pixmap for drag and drop
you need to reimplement paintEvent and draw that pixmap.
Re: Creating a Pixmap for drag and drop
I tried QPixmap::grabWidget and it only grabs the background. What I draw on the frame in paintEvent is lost. :(
Is there really no other way? If I reimplement paintEvent then I have to write the painting code for every different kind of widget twice. Plus the style sheet is not applied, so I have to figure out a way to transfer the style from the widget to the QImage. It's ugly and cumbersome. There must be a generic way.
Re: Creating a Pixmap for drag and drop
take a look at this example QTDIR/examples/draganddrop/draggableicons
Re: Creating a Pixmap for drag and drop
In that example the pixmaps are loaded from images.
Re: Creating a Pixmap for drag and drop
yes, but you can create needed image and then use it like in that example.
Re: Creating a Pixmap for drag and drop
Have a look at QWidget::render
You can render on to a pixmap which is a paintdevice :)
Re: Creating a Pixmap for drag and drop
When creating the images I'm facing the same problem: how to create them in a generic way.
I'm trying this approach:
Code:
/* A paint function, that takes a painter as an argument.
* It's supposed to paint the contents of the frame either
* on the frame itself or on a pixmap. */
void KeyFrame
::myPaint(QPainter* painter
) {
painter->setPen(Qt::black);
painter->drawText(0, 0, "hello Qt");
}
/* The frame is drawing itself on the gui. */
{
QPainter painter
(this);
// Construct a painter that draws on this frame. myPaint(&painter); // Pass it to my painter.
}
/* Drag action starting. */
{
/* Prepare a pixmap for the drag that will be moved along with the mouse. */
// Grab the widget so you get a styled background.
// Initialize a painter that draws on the pixmap....
painter.begin(&pixmap); // ...and pass it to my painter.
myPaint(&painter);
painter.end();
// Create the drag object.
drag->setPixmap(pixmap);
}
But it doesn't work. What I paint on the pixmap is not shown. Do you see an error?
Re: Creating a Pixmap for drag and drop
Quote:
Originally Posted by
aamer4yu
Have a look at
QWidget::render
You can render on to a pixmap which is a paintdevice :)
That would be perfect! But again, it doesn't work.
Code:
{
if (event->button() == Qt::LeftButton)
{
// Prepare the mime data for the drag.
mimeData->setText("hello");
this->render(&pixmap);
// Create the drag object.
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
Qt::DropAction dropAction = drag->exec();
}
}
The drag starts and all I see is a blank rectangle of the right size, but with the window background color. Not even the frame background color actually. Neither the style is applied, nor are the contents of the frame rendered. Am I not doing something right?
Re: Creating a Pixmap for drag and drop
try this (modificated draggableicons example)
Code:
{
dataStream << pixmap <<
QPoint(event
->pos
());
mimeData->setData("application/x-dnditemdata", itemData);
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(event->pos());
painter.drawText(pixmap.rect().center().x(), pixmap.rect().center().y(), "hello Qt");
drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
}
NOTE: you must set setAcceptDrops(true) in Test::ctor.
PS. read more about Drag&Drop
Re: Creating a Pixmap for drag and drop
I tried it by copy&paste. It also doesn't work. All I see is a rectangle of the right size and the wrong background color and nothing written on it. Also tried not grabbing the pixmap, but just initializing a blank one and then drawing on it: nothing. Not working. Here is the simplest example I can image:
Code:
{
painter.drawText(pixmap.rect().center().x(), pixmap.rect().center().y(), "hello Qt");
mimeData->setText("hello");
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(event->pos());
drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
}
Not working. I tried amoving the pixmap to the heap, but that doesn't help either. I'm out of ideas.
Re: Creating a Pixmap for drag and drop
did you set 'setAcceptDrops(true)'?
Re: Creating a Pixmap for drag and drop
I can drag and drop the frame into a QLineEdit and it will show whatever I set as text into the MimeData. So I assume this line edit has its accept drops set to true. The drag itself works fine. The problem is only related to what the drag looks like. In particular I don't seem to be able to draw on the pixmap. I don't thing the accept drops has anyhting to do with it.
Re: Creating a Pixmap for drag and drop
this example works fine for me, but it is not complite, just demo for creating and moving grabbed image.
Code:
#include <QtGui>
#include "test.h"
{
pb->installEventFilter(this);
cb->installEventFilter(this);
chb->installEventFilter(this);
rb->installEventFilter(this);
sb->installEventFilter(this);
dsp->installEventFilter(this);
grid->addWidget(pb, 0, 0);
grid->addWidget(cb, 0, 1);
grid->addWidget(chb, 0, 2);
grid->addWidget(rb, 1, 0);
grid->addWidget(sb, 1, 1);
grid->addWidget(dsp, 1, 2);
setCentralWidget(widget);
setAcceptDrops(true);
}
{
processDrag(this, event);
}
{
painter.setPen(Qt::red);
painter.drawText(0, pixmap.rect().center().y(), "hello Qt");
dataStream << pixmap <<
QPoint(event
->pos
());
mimeData->setData("application/x-dnditemdata", itemData);
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(event->pos());
drag->exec();
}
{
if (e
->type
() == QEvent::MouseButtonPress) { QWidget *widget
= qobject_cast<QWidget
*>
(o
);
if (widget && me->button() == Qt::LeftButton) {
processDrag(widget, me);
return true;
}
}
}
Re: Creating a Pixmap for drag and drop
Wow! Thanks a lot for all the effort you are putting into this. I built a project from your example and it works for me too. Now I need to scrutinize the differences and see which bit is responsible.
Re: Creating a Pixmap for drag and drop
I found the bugger! It's the style sheet.
Code:
background-color: beige;
}
With this I set the bg color of the application. If I take this out, the drag looks like it should. If this is back in, the drag is only a beige rect.
Why is the style sheet influencing the drag this way? The drag itself is not a widget is it?
I tried taking this out of my style sheet and explicitly setting the background of my main window (which is a QWidget and not a QMainWindow in my case) in Designer. It has the same bad effect on the drag.
So the last thing to figure out is how to set a background color for the application AND have nice looking drags.
Re: Creating a Pixmap for drag and drop
try to use QPalette insted of using style sheets.
Re: Creating a Pixmap for drag and drop
Yes, the palette works. At the end using style sheets brought me more trouble than good. It's nice how you can change the appearance easily by editing a singe style sheet and not even have to recompile for it. But it doesn't look the same on Windows and on Linux and there is troubles like with the drag. There is still nothing like pixel exact coding. :)