Announcement

Collapse
No announcement yet.

Zeichnen mit QT

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Zeichnen mit QT

    Hallo,

    ich möchte zum Test ein "Spielfeld" als Matrix zeichnen. Hier mal mein Testcode:

    Code:
    QPixmap  pixMap(_playingField_x_width, _playingField_y_height);
        QPen     pen;
        QPainter playingField(&pixMap);
        
        //Draw Playing Field
        pen.setColor(Qt::black);
        pen.setStyle(Qt::SolidLine);
        pen.setWidth(0);
        playingField.setPen(pen);
        //pixMap.fill(Qt::blue);
        int counter = 0;
        for (int x = 0; x < _playingField_x_width + 1; x++) //x
        {
            for (int y = 0; y < _playingField_y_height +1; y++) //y
            {
                playingField.drawPoint(x, y);
            }
            counter ++;
        }//end for x
        playingField.end();
        
        ui->labelPlayingField->setPixmap(pixMap);
    
        ui->lineEditCounter->setText(QString::number(counter));
    Folgende Probleme habe ich:
    1. Das Programm ist arsch langsam! Gibt es eine Möglichkeit die Matrix im Speicher zu berechnen und dann einfach in bspw. ein Label zu schieben?
    2. Welche Größe nehme ich für Pan?

    Vielen Dank im Voraus.

    Grüße
    MaX

  • #2
    Sicherlich ist es langsam, wenn du jeden Punkt einzeln zeichnest. Das ist so ziemlich die langsamste Operation um eine Grafik aufzubauen. Was nun die berechneten Daten in einem Label sollen, erschließt sich mir nicht. Da keiner weiss, was du überhaupt darstellen willst, kann man schlecht Hinweise geben, wie es besser geht. So allgemein: fertige Zeichnung als Gundlage, Linien, Dreicke o.a. zeichnen. Wozu gibt es eine Variable Counter? Welchen Wert anders als x könnte sie haben. Letztlich kostet so etwas auch Zeit

    int x; for ( x = 0
    Christian

    Comment


    • #3
      Hallo Christian,

      da ich mit der vcl gelernt habe, bin ich der Meinung eine Zeichnung in einer Komponente zu machen!? Wie das bei QT aussieht weis ich leider nicht.

      Ich zeichne jedes Pixel einzeln, da jedes Pixel später einen beliebigen Wert(Farbe) annehmen können soll.
      Die Counter-Variable war falsch platziert, sie gehört eigendlich in die y-for-schleife.

      Grüße
      MaX

      Comment


      • #4
        da ich mit der vcl gelernt habe, bin ich der Meinung eine Zeichnung in einer Komponente zu machen!?
        In der VCL wurde auf einem Canvas gezeichnet. Jede Komponente hat dort einen Canvas gehabt, da auch jeder Komponente ja irgendwie gezeichnet werden muss. Deshalb wäre allerdings auch bei der VCL kaum einer auf die Idee gekommen, etwas im einem TLabel zu zeichnen. Entweder man zeichnete auf dem Canvas der TForm oder in einer TPaintBox...

        Ich zeichne jedes Pixel einzeln, da jedes Pixel später einen beliebigen Wert annehmen können soll.
        Es weiss immer noch keiner, was du zeichnen willst und ob es einfacher geht. Grundsätzlich ist es aber dann sinnvoll

        - die Erstellung der Grafik und
        - die Änderung eines Pixels

        zu trennen.

        Bloß weil man irgendwann mal ein Pixel ändern möchte, jetzt alle Daten in einem Array o.a. zu halten und danach zu zeichnen erscheint wenig sinnvoll. Vielmahr sollte die Grafik erstellt werden und dann ein Weg gefunden werden, wie man an den Pixel, den man ändern möchte, herankommt.
        - Berechnung
        - Daten in einem Array halten, aber nicht damit zeichnen
        - ...
        Zuletzt editiert von Christian Marquardt; 30.12.2012, 11:33.
        Christian

        Comment


        • #5
          Und wie ist es nun bei QT? Ich zeichne also einfach auf das MainWindow? Ich fand jedoch die Kapselung in einer Komponente ganz angenehm, da die Zeichnung dann immer abhängig von Größe und Position der jeweiligen Komponente ist.

          Die Idee hatte ich auch schon, dass ich eine einmal berechnete Grafik nehme und diese bei Bedarf an bestimmten Stellen ändere.
          Nur habe ich keine Ahnung wie ich das umsetzen soll. Deswegen bin ich hier und frage.

          Grüße

          Comment


          • #6
            Nur habe ich keine Ahnung wie ich das umsetzen soll. Deswegen bin ich hier und frage.
            Dann liest dir deinen Beitrag durch. Kein Mensch weiss was du machen willst (was für ein Spiel, was wird gezeichnet, wann erfolgt die Änderung, aufgrund welches Ereignisses, welche Daten stehen zur Vefügung). Wie sollte dir jetzt jemand sagen, wie du einen deiner Pixel änderst?

            Beispiel:
            Wenn du ein Memory-Spiel programmierst und die Karten schön in Reih und Glied liegen, kann man ganz einfach die gewünscht Karte, Reihe und Spalte berechnen und dann auch die Karte ändern.

            Also ich sage ganz einfach mal: Wenn der Anwender mit der Maus klickt, wird der Pixel an der Stelle schwarz. Das sollte jetzt die Lösung für dich sein.
            Christian

            Comment


            • #7
              http://de.wikipedia.org/wiki/Wator

              Ich habe das schonmal vor einigen Jahren in der Ausbildung mit Borland programmiert.
              Jetzt sitz ich schon seit drei Jahren an einer "Neuauflage" - zum Spaß. Ich programmiere aller vier Monate drei Stunden daran....die Zeit fehlt.

              Die komplette Logig ist implementiert und getestet. Alles was fehlt ist die Darstellung.
              Ich programmiere das ganze mit cmake in xcode.

              Ich fand die Idee es mit QT abzubilden ganz nett. Ich habe aber keine Ahnung von QT.

              Was will ich:
              Ich will beispielsweise ein Spielfeld 600 * 600 abbilden.
              Ein Punkt in der Matrix stellt ein Lebewesen dar.
              Es gibt drei Formern: Fisch, Hai und Wasser

              Konkret:
              - Wie kann ich meine Anforderungen in QT darstellen?
              - Wie mache ich das performant?
              - Welche QT-Klassen muss ich dazu verwenden, was bietet sich an?
              - Wie mache ich das elegant?

              Grüße

              Comment


              • #8
                Da würde ich doch die OOP nutzen. Das Speilfeld ist eine Klasse (bsp. Feld). Diese enthält wiederum je nach Größe des Spielfeldes ein 2 dim. Array (Größe des Feldes) mit Objekten des Typs Zelle. Jedes Objekt Zelle hat die Eigenschaften

                - Typ (Hai, Fisch, leer)
                - Position (x,y)
                - Größe (width, height )
                - Farbe
                - usw.

                Beim ersten Aufbau des Spielfeldes werden alle Zellen ja in Reihen und Spalten gesetzt. Es kann folglich für jede Zelle die Position und Größe in derselben gespeichert werden. Wird es nun durch ein Ereignis erforderlich, dass in der Zelle etwas geändert wird (Hai,Fisch,leer), so kannst du gezielt diese Zelle neu zeichnen, da du ja Position und Größe weisst.

                Das wäre mal so ein übergreifender Ansatz. Und es wäre schnurz, ob das VCL, QT, JAVA o.a. ist

                EDIT

                Der mag helfen: http://doc.qt.digia.com/qq/qq19-graphicsview.html

                Sollen alle Zellen auf einmal gezeichnet werden, kann dies in Threads ausgelagert werden. Je nach Zellenanzahl bearbeiten die Threads "ihre" Zellen.
                Zuletzt editiert von Christian Marquardt; 30.12.2012, 13:34.
                Christian

                Comment


                • #9
                  Das Design und die Implementierung ist bereits komplett. Habe das mit Vererbung gelöst, dabei stellt jedes Lebeweisen eine abgeleitete Klasse der Basisklasse Individuum dar.

                  Wie gesagt, was fehlt ist das Visualisieren. Ich lese mir mal den Link von Dir durch. Mal sehen ob ich ne Darstellung auf die Reihe bekomme.

                  Grüße

                  Comment


                  • #10
                    Dann wäre

                    Jedes Objekt Zelle hat die Eigenschaften


                    - Position (x,y)
                    - Größe (width, height )
                    - Object der Klasse Individuum

                    möglich.
                    Christian

                    Comment


                    • #11
                      Die Lebewesen werden generiert und in einem zweidemensionalen Vector gespeichert:

                      Code:
                      typedef std::vector<TIndividual *> TColumn;
                      typedef std::vector<TColumn> TPlayingFieldMatrix;
                      
                      TPlayingFieldMatrix _playingFieldMatrix;
                      Die größe des Spielfelds kann abgefragt werden:

                      Code:
                       
                      typedef std::pair<long, long> TWorldSize;
                      inline TWorldSize getWorldSize() const;
                      Das Spielfeld besteht also aus x * y Feldern. Die einzelnen, sich darauf befindenden Lebewesen bzw. Spielfelder, können über folgende Methode abgefragt werden:

                      Code:
                       
                      int getIndividumType(long xPos, long yPos) const;
                      Ich hatte mir nun vorgestellt, das komplette spielfeld abzufragen und je nach Typ eine bestimmte Farbe zu zeichnen.

                      Grüße

                      Comment


                      • #12
                        Dann versuche das in Threads auszulagern. Thread1 zeichnet von Reihe 1-50, Thread2 von 51-100....

                        Weitere Möglichkeit wäre direkte Manipulation der Bitmapdaten. Letzlich besteht ein Punkt aus einem 4 Byte Wert. RGB und Reserve bzw. Alphakanal. Man könnte also den Speicher der Bitmapdaten durchlaufen und überall eine entsprechenden Wert reinsetzen. Weiss jetzt allerdings nicht wie man unter QT an diesen Speicher kommt
                        Christian

                        Comment


                        • #13
                          Das übersteigt leider meine QT-Kenntnisse...

                          Comment


                          • #14
                            http://doc.qt.digia.com/qt/qpixmap.h...map-conversion

                            Das wäre ein Einstieg. Dort gibt es Methoden (toWinHBITMAP) um die Daten zu bekommen

                            Hier ein Beispiel für Threaderstellung
                            http://doc.qt.digia.com/qt/threads-starting.html
                            Christian

                            Comment


                            • #15
                              Irgendwie finde ich das interessant. Mal eine Frage zu den Regeln:

                              Jeder Fisch hat ein Alter; überschreitet dieses Alter die "Breed Time", so wird auf einem leeren, angrenzenden Feld ein neuer Fisch geboren.
                              Was macht das für ein Sinn, den eine Fisch raus zu nehmen undmit einem? neuen zu ersetzen?
                              Christian

                              Comment

                              Working...
                              X