take screenshot without one specific program window - c++

I need to take a regular screenshot but i need for a way to disregard an open application. In the screenshot must appear the regular background as if the application/window wasn't open.
In other words, i need one screenshot without an window/aplication (which is presemnt) but appearing what is behind of this window/aplication, disregarding the window/ap.
For get screenshot i have the folowing code in QT/c++:
(...)
QScreen *screen = QGuiApplication::primaryScreen();
QPixmap qPImage = screen->grabWindow(0);
QImage qImg = qPImage.toImage();//convert to qImage
(...)
It is possible do what i need?
Regards
Alex

May be not the perfect solution, but this is what I did in the exact same situation:
void MainWindow::onUpdateClicked()
{
hide();
QTimer::singleShot(45, this, SLOT(updateScreenshotPicture()));
}
void MainWindow::updateScreenshotPicture()
{
screenshotBorders->setPic(QPixmap::grabWindow(QApplication::desktop()->winId()));
show();
}

Related

Qt event when anything changed on the window/screen + Screenshot

I'm thinking of extending a QT4 application with some debug possibilities, to make it easier analyzing customer issues. The application already has a "Debug" mode, when this is enabled, a lot of log entries generated, which is hard to read.
What I would like to achive is taking a screenshot of the application, whenever something is changed on the GUI. I know that it may take a lot of pictures, but generally Debug mode is not enabled for a long time. The problem is I cannot find such an event/signal. So I have two question:
Is there such an event I could subscribe? I mean, an event that is
fired whenever anything changes on the screen.
Can I take a screenshot of the application using Qt?
Thanks in advance!
I'd do it using an event filter and a QTimer, something like this:
class MyEventFilter : public QObject
{
public:
MyEventFilter() : _screenshotPending(false) {/* empty */}
virtual bool eventFilter(QObject * o, QEvent * e)
{
if (e->type() == QEvent::Paint)
{
if (_screenshotPending == false)
{
// we'll wait 500mS before taking the screenshot
// that way we aren't trying to take 1000 screenshots per second :)
_screenshotPending = true;
QTimer::singleShot(500, this, SLOT(TakeAScreenshot()));
}
}
return QObject::eventFilter(o, e);
}
public slots:
void TakeAScreenshot()
{
_screenshotPending = false;
// add the standard Qt code for taking a screenshot here
// see $QTDIR/examples/widgets/desktop/screenshot for that
}
private:
bool _screenshotPending; // true iff we've called QTimer::singleShot() recently
};
int main(int argc, char ** argv)
{
MyEventFilter filter;
QApplication app(argc, argv);
app.installEventFilter(&filter);
[...]
return app.exec();
}
Generally, when some widget changes Qt needs to repaint it, so the event you would be interested in is QEvent::Paint. The problem here is that there will be tons of these events for widgets that overlap each other. You can override QApplication::notify() to catch all paint events before they are even delivered to receivers.
As for making screenshots of Qt application - there are several similar questions here on SO, for example screenshot of a qt application from inside the application or Taking screenshot of a specific window - C++ / Qt
Here is also a thread discussing dumping widgets to images in paintEvent().
As for your second question, here is some of my old code that can take a screenshot of a window. You can use this code like so:
HDC WinDC = GetDC(HWND_OF_YOUR_WINDOW);
HBITMAP image = ScreenshotUtility::fromHDC(WinDC);
Then you can convert the HBITMAP to a Qt Pixmap object and work with it how you like: QPixmap pixmap = QPixmap::fromWinHBITMAP(image);.
EDIT: this is Windows-specific code, not sure what the equivalent on other systems may be.

Make a QLabel blink

I'm using Qt to make a gui application for my beagleboard.
I'm trying to make a QLabel blink with a custom image.
QTimer::connect(timer, SIGNAL(timeout()), this, SLOT(blink()));
timer->start(1000);
I'm thinking to use QTimer to call the blink() function every second, but I do not have a clue what the code should be in blink() function. I hope someone can help, since i have struggle with this problem in a while now.
Create blinking animation in a GIF file.
Create whatever animation you like with tools like GIF Animator.
Show it like below:
auto movie = new QMovie("myblinking.gif");
QLabel blinklabel = new QLabel();
blinklabel->setMovie(movie);
movie->start();
The easiest way is to hide and show it again.
Class::blink()
{
if(label->isHidden())
label->show();
else
label->hide();
}
This approach is good because you don't need to set your image again and again, just show/hide it(set empty pixmap or set image every second is not efficient approach).
If you use layout, then it can really break your layout, so you can use QStackedWidget with imageLabel and empty label and change it every second. I think that it will be still better than set empty pixmap or set image every second. Choose the best for you.
http://qt-project.org/doc/qt-4.8/qstackedwidget.html
Using a bool member isQLabelVisible in your class
Class::blink() {
if(isQLabelVisible) {
doHideQLabel();
isQLabelVisible = false;
} else {
doShowQLabel();
isQLabelVisible = true;
}
}
void Class::doHideQLabel() {
[...]
}
void Class::doShowQLabel() {
[...]
}
You have a starting point for a good solution. Now, to implements do{Hide,Show}QLabel(), read answers from this question and decide which one is the best for your needs.

Qt QGraphicsScene does not fitInView() with scrollbars

QGraphicsView::fitInView() seems to ignore the presence of scrollbars, that apparently are overlaid. (It also uses a hardcoded 2 pixel margin.)
There is a related bug report (https://bugreports.qt-project.org/browse/QTBUG-1047) stating that calling fitInView() twice would resolve the problem.
In my case, it does not. Only triggering it twice manually fits regarding the scrollbars. This does not work:
void myGraphicsView::mousePressEvent(QMouseEvent *event) {
if( event->button() == Qt::LeftButton ) {
QGraphicsItem* clicked = scene()->itemAt( mapToScene( event->pos() ) );
qDebug() << clicked << clicked->boundingRect();
fitInView( clicked, Qt::KeepAspectRatio);
fitInView( clicked, Qt::KeepAspectRatio); // doesn't work for me
QGraphicsView::mousePressEvent(event);
return;
}
}
Is there another workaround?
Qt 4.8.1 with MSVC2010
Calling fitInView() twice does work, but you have to let Qt process its events between the two calls.
This also means you end up redrawing the graphicsview twice.
To avoid this, what I do is:
Disable updates
Call fitInView
Call QApplication::processEvents()
Call fitInView again
Enable updates
In your code it would look like this:
bool updateState = updatesEnabled();
setUpdatesEnabled(false);
fitInView(clicked, Qt::KeepAspectRatio);
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
fitInView(clicked, Qt::KeepAspectRatio);
setUpdatesEnabled(updateState);
The cause could be this (at least it looks like it is in the bug report): https://bugreports.qt.io/browse/QTBUG-42331 - please vote on it on the qt bug tracker to up its priority.
In short, fitInView has hardcoded margins and this can cause all kinds of havoc - the least of which is that now you lose a few pixels of display area and might also force unnecessary rescaling. It can cause runaway resizing and weird instabilities such as what the QTBUG-1047 bug submitter described.
You can fix the problem by reimplementing fitInView, based on the existing implementation but removing it's ridiculous margins. An example of that is available here in python, based on the original C++ version:
https://github.com/nevion/pyqimageview/blob/master/qimageview/widget.py#L276
Let me know if it fixes your problem! That way we can close out that since-2007 bug too.

How can I show an image widget on top of a Button

refBuilder->get_widget("image1", image);
if(image){
pButton1->set_image(*image);
//Glib::PropertyProxy<bool> prop;
Gtk::Settings::property_gtk_button_images() = true;
}
I know the last line isn't written properly, I don't know how to use PropertyProxy. I just want to set the property to true. that might not solve what I want to achieve, but it might be a step closer. The class reference didn't specify how to use them properly. Any suggestions?
I am not sure what are you looking for but if you want to put an image on a button, then here is the code. Basically you need to define an image and set that image to the given button.
Gtk::Button *btn=Gtk::manage(new Gtk::Button("DummyButton"));
Gtk::Image *ImageIcon=Gtk::manage(new Gtk::Image(Gtk::IconTheme::get_default()->load_icon("ButtonImage",128)));
btn->set_image(*ImageIcon);
btn->set_image_position(Gtk::POS_TOP);

Using images in QListWidget, is this possible?

I am using QT to create a chat messenger client. To display the list of online users, I'm using a QListWidget, as created like this:
listWidget = new QListWidget(horizontalLayoutWidget);
listWidget->setObjectName("userList");
QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Expanding);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(listWidget->sizePolicy().hasHeightForWidth());
listWidget->setSizePolicy(sizePolicy1);
listWidget->setMinimumSize(QSize(30, 0));
listWidget->setMaximumSize(QSize(150, 16777215));
listWidget->setBaseSize(QSize(100, 0));
listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
Users are shown by constantly refreshing the list, like this: (Note: There are different channels, with different userlists, so refreshing it is the most efficient thing to do, as far as I know.)
void FMessenger::refreshUserlist()
{
if (currentPanel == 0)
return;
listWidget = this->findChild<QListWidget *>(QString("userList"));
listWidget->clear();
QList<FCharacter*> charList = currentPanel->charList();
QListWidgetItem* charitem = 0;
FCharacter* character;
foreach(character, charList)
{
charitem = new QListWidgetItem(character->name());
// charitem->setIcon(QIcon(":/Images/status.png"));
listWidget->addItem(charitem);
}
}
This has always worked perfectly. The line that I commented out is the one I have problems with: my current goal is to be able to display a user's online status with an image, which represents whether they are busy, away, available, etc. Using setIcon() does absolutely nothing though, apparently; the items still show up as they used to, without icons.
I'm aware that this is probably not the way this function needs to be used, but I have found little documentation about it online, and absolutely no useful examples of implementations. My question is, can anybody help me with fixing this problem?
This is how you may conduct your debugging:
Try the constructor that has both icon and text as arguments.
Try to use that icon in another context to ensure it is displayable (construct a QIcon with same argument and use it elsewhere, e.g. QLabel!).
Use icon() from the QListWidgetItem to receive back the icon and then look at that QIcon.
Create a new QListWidget, change nothing, and ordinarily add some stock items in your MainWidget's constructor. See if the icons show up there.