[GELÖST] Mit QPainter auf MainWidget zeichnen



  • Hi!

    Ich stehe wieder vor einem Problem bei meinem Sudoku Programm.
    Hier erstmal die main Funktion:

    int main(int argc, char *argv[])
    {
        QApplication app(argc,argv);
        QWidget *w=new QWidget();
    
        w->setFixedSize(300,320);
        w->setWindowTitle("Qudoku by Langi");
    
        Qudoku qd(w);
        qd.StartQGame();
    
        w->show();
    
        return app.exec();
    }
    

    In der Funktion StartQGame werden alle Eingabefelder und Buttons auf dem Widget w erstellt:
    http://img46.imageshack.us/img46/9086/bildschirmfoto20100609u.png

    Jetzt möchte ich wegen der Übersichtlichkeit jeweils die 3x3-Kästchen mit Linien trennen. Nun habe ich gelesen, dass ich nicht direkt auf mein MainWidget zeichnen kann, sondern dazu ein eigenes Widget erstellen muss. Der Versuch ist jedoch kläglich gescheitert.

    Ich habe folgende Klasse erstellt:

    class PaintWidget : public QWidget {
    
        Q_OBJECT
    
        void paintEvent(QPaintEvent *) {
            QPainter painter(this);
            painter.setPen(Qt::blue);
            painter.drawLine(100,20,100,100);
        }
    };
    

    In der main Funktion habe ich dann statt des QWidget ein QMainWindow erstellt und das PaintWidget per w->setCentralWidget(new Paintwidget()) "eingebunden".
    Das Resultat war, dass ich nun zwar die Linie gesehen hab, allerdings die Eingabefelder nimmer und die Buttons auch abgeschnitten wurden.
    http://img163.imageshack.us/img163/1002/bildschirmfoto20100609uz.png

    Wie bekomm ich denn nun am Einfachsten diese simplen Linien in mein Programm?

    mfg



  • selbstverständlich kannst du auch direkt auf dem QMainWindow zeichnen. Ein kurzer Test würde das bestätigen.

    Andere Möglichkeiten: die anderen Widgets ebenfalls ins PaintWidget verfrachten oder den Hintergrund des PaintWidgets transparent machen ( QWidget::setAutoFillBackground(false) )



  • Was hat das Ganze mit autoFillBackground zu tun? Das würde doch nur heißen, dass das alles verdeckt werden würde, was nicht erklärt, warum die Buttons abgeschnitten werden. Der Versuch das zu ändern war außerdem erfolglos.

    Wie würde denn dieser "kleine Test" aussehen? Ich bekomms nicht hin, dass ich eine Linie sehe.

    Ich habe jetzt mal diese Funktion in meine Klasse gepackt:

    void paintEvent(QPaintEvent *) {
            QPainter painter;
            painter.begin(this);
            painter.setPen(Qt::blue);
            painter.drawLine(100,20,100,100);
            painter.end();
        };
    

    Wie rufe ich diese nun auf? Ich bin aus der ganzen Doku leider nicht schlau geworden, bzw dachte ich schon, ich hätte es verstanden, jedoch sehe ich immer noch nichts. Ein direkter Aufruf funktioniert ja nicht.

    Ich hoffe Ihr könnt mir helfen, das zu VERSTEHEN. An irgendeinem Punkt happerts nch gewaltig.

    mfg



  • paintEvent wird automatisch aufgerufen. So ist es mit allen Event-Methoden.
    Die übliche Implementierung:

    // .h
    class MyWindow : public QMainWindow
    {
    ...
    protected:
       void paintEvent(QPaintEvent*);
    };
    
    // .cpp
    MyWindow::paintEvent(QPaintEvent*)
    {
       QPainter painter(this);
    
       painter.drawLine(...);
    }
    

    wenn autofillBackground true ist, dann wird bei jedem PaintEvent zuerst der Hintergrund gefüllt, bevor gezeichnet wird. Setzt man es auf false, bleibt er transparent.

    Warum die Buttons abgeschnitten werden, kann ich von hier aus nicht sagen. Ich denke aber, dass es mit "setCentralWidget" zusammenhängt. Ich würde dir empfehlen, die Eingabefelder und die Linien in ein Widget zu packen.



  • So siehts nun aus bei mir. Ich habe zusätzlich autoFillBackground auf false gesetzt bei allen Sachen, die hier die Linien verdecken könnten. Leider sehe ich trotzdem nichts.

    Laufzeitfehler bezüglich paintEvent bekomme ich keine mehr, also müsste das eigentlich funktioniert haben. Schön langsam wirds schwierieg, Ferndiagnosen ohne sehr viel Code zu stellen denk ich mir.



  • Und wieso lässt du das Mainwindow nicht erst alles zeichnen und zeichnest anschliessend deine Linien darüber?

    class MyWindow : public QWidget
    { 
    ...
    }
    
    MyWindow::paintEvent(QPaintEvent *event)
    {
       QWidget::paintEvent(event);
       QPainter painter(this);
       painter.setPen(QPen(Qt::black));
       painter.drawLine(...);
    
    }
    


  • Danke nochmals für alle Antworten.
    Ich habs gelöst, warum ich das nicht früher geschafft habe... Ich hatte einfach immer eine Kleinigkeit falsch, was zu einem falschen Resultat führte.

    So siehts nun aus...

    class PaintWidget : public QWidget
    {
        Q_OBJECT
    
    public:
        PaintWidget(QWidget *parent=0);
    
    protected:
        void paintEvent(QPaintEvent *);
    };
    
    PaintWidget::PaintWidget(QWidget *parent)
          : QWidget(parent)
     {
         resize(parent->width(),parent->height());
     }
    
    void PaintWidget::paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
        painter.setPen(Qt::black);
    
        painter.drawLine(97,10,97,277);
        //...
    }
    

    Und anschließend noch eine Instanz der Klasse erstellt und passt.


Log in to reply