views:

170

answers:

2

Hi All,

I am writing an info-screen program. I created a full-screen widget and draw contents onto it.

In order to extend the life cycle of the TFT-display device, I want to implement a pixel-shifting feature. With other words, in every X minutes, I shift the screen to left/right/top/down for Y pixels.

My approach is as follows:

  1. I use two layers (two QWidget).
  2. I paint contents on the top layer.
  3. When a pixel-shifting is performed, I just move the top layer for specified offset.
  4. And then fill a background color to the bottom layer.

However, I found a problem:

If I move up the top layer for 10 pixels, the 10-pixel-content goes out of the screen. But when I move this layer down for 10 pixels. The 10-pixel-content will not be updated, it is gone.

How can I keep these 10-pixel-content? Is there any magic widget flag to solve this problem?

UPDATE 1: The code is written in language D, but it is easy to understand:

class Canvas: QWidget
{
    private QPixmap content;

    this(QWidget parent)
    {
        super(parent);
        setAttribute(Qt.WA_OpaquePaintEvent, true);
    }

    public void requestForPaint(QPixmap content, QRegion region)
    {
        this.content = content;
        update(region);
    }

    protected override void paintEvent(QPaintEvent event)
    {
        if (this.content !is null)
        {
            QPainter painter = new QPainter(this);
            painter.setClipping(event.region);
            painter.fillRect(event.region.boundingRect, new QColor(0, 0, 0));
            painter.drawPixmap(event.region.rect, this.content);
            this.content = null;
            painter.setClipping(false);
        }
    }
}

class Screen: QWidget
{
    private Canvas canvas;

    this()
    {
        super(); // Top-Level widget
        setAutoFillBackground(True);
        this.canvas = new Canvas(this);
        showFullScreen();
    }

    public void requestForPaint(QPixmap content, QRegion region)
    {
        this.canvas.requestForPaint(content, region);
    }

    private updateBackgroundColor(QColor backgroundColor)
    {
        QPalette newPalette = palette();
        newPalette.setColor(backgroundRole(), backgroundColor);
        setPalette(newPalette);
    }

    public shiftPixels(int dx, int dy)
    {
        this.canvas.move(dx, dy);
        updateBackgroundColor(new QColor(0, 0, 0)); // Just a demo background color
    }
}

Screen screen = new Screen;
screen.requestForPaint(some_content, some_region);
screen.shiftPixels(0, -10);
screen.shiftPixels(0, 10);
+2  A: 

Looking at the code, my first guess is that your region might be wrong. Try repainting the whole widget each time, and see if that solves the missing 10 pixel problem. If it does, then try working out why your region isn't covering the newly exposed portion.

One possibility along those lines: I notice in your Screen::requestForPaint method that you directly call the Canvas::requestForPaint without doing anything with the region. In Qt, the coordinates for anything like that are often assumed to be local, so if you don't account for the current position of the canvas widget, you might get an incorrect region.

Caleb Huitt - cjhuitt
My application runs in full screen, no mouse no keyboard are connected. The canvas will not get dirty normally. So, I only have to make sure that the newly painted area looks well. However, if the canvas gets dirty, it is impossible for me to repaint the whole canvas, because I have not saved the information about how the whole screen should be painted. (Of course there are some ways to save the screen contents)I just wondered, the content of a QWidget goes lost, when I move it out of the screen and then move it back. And I am looking for solution for it.
stanleyxu2005
BTW: The reason, why I do not paint the whole screen every time, is that I have some marquee text on the screen. If I repaint everything in 20ms, the cpu usage will be high.
stanleyxu2005
+1  A: 

Why not setting the position of the widget directly...? Another options might be using QPainter::translate(-1,-1) or something similar.

elcuco
do you mean, I should just use one canvas instead of two. And I should print content with QPainter::translate(dx, dy)? But this does not solve my problem.I might paint some contents at top left. After 30 seconds I paint some other contents at bottom right. The rest area stays unchanged. After another 30 seconds, I want the whole canvas to be shifted. At this moment, so the easiest way is just move the widget, isn't it?
stanleyxu2005