Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?



  • Hallo,
    ich bin noch Anfänger mit Qt, habe aber schon Erfahrung mit Javascript und teilweise C++. Mit Qt Widget habe ich grafische Objekte, Text und ein Bmp-Bild "gezeichnet". Das klappt soweit ganz gut, allerdings möchte ich konkret erreichen, dass das angezeigte Window 1900x1000 pixel und der scrollbare Inhalt jedoch 1900x2140 pixel umfassen soll (die 1900x1000 pixel des Windows stelle ich im Designer ein, kein Problem). Dass ich wohl ein Child-Window erstellen muss, um den größeren Inhalt darzustellen, ist mir klar. Allerdings habe ich im Web nichts passendes gefunden, wie ich das Ganze bewerkstelligen kann.

    Ich hoffe, jemand kann mir dazu weiterhelfen.
    Viele Grüße,
    Stefan



  • @stefanpc81

    Ich versteh zwar noch nicht ganz genau was du vorhast, aber würde jetzt spontan eine QScrollArea empfehlen. Die Größe des eigentlichen Widgets / Windows ist ja unabhängig davon.

    @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Dass ich wohl ein Child-Window erstellen muss, um den größeren Inhalt darzustellen, ist mir klar.

    Nö, musst du nicht unbedingt.

    Das Window kann ja fixed oder minimum 1900x1000 haben. Darin ist dann der scrollbare Bereich, der sich mehr oder weniger automatisch scrollen lässt, wenn der Inhalt über die Grenzen des Bereichs hinausgeht (bei 1900x2140).

    Eventuell würde ich einen Blick auf QGraphicsView werfen...wie gesagt, je nachdem was das am Ende werden soll ;-)
    -> "graphische Objekte"



  • @Pl45m4 Danke soweit. Ich weiß nicht, ob ich dich richtig verstanden habe, jedenfalls zeigt mir mein Fenster keine Scrollbars an, wenn ich in meinem graphics.cpp folgendes steht:

    ...
    #include <QScrollArea>
    
    Graphics::Graphics(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::Graphics)
    {
        ui->setupUi(this);
        QScrollArea scrollArea;
        scrollArea.setWidget(parent);
    }
    ...
    

    und ich im Design des Fensters die "MaximumSize" auf 1900x2140 einstelle. Ist das so richtig?

    cockpit.jpg

    Der Screenshot zeigt einen Ausschnitt aus meinem Cockpitsimulator eines Flugzeugs (hier noch mit HTML/Javascript). Was ich mit Grafiken meinte, ist folgendes:
    Der gesamte Inhalt ist wie gesagt 1900x2140 pixel groß, ist grundlegend überall in beige dargestellt und hat noch folgende Inhalte:
    Über die gesamte Fläche müssen einzelne Schalter und Taster angezeigt werden (als Rechteck mit Text oder Images), die mit einem Mausklick Funktionen/Methoden aufrufen sollen. desweitern möchte ich gerne, dass auf die Monitore (im Bild die beiden großen Rechtecke, insgesamt aber 4 große und ein kleinerer) nach Möglichkeit über jeweils eine eigene Klasse oder zumindest getrennt über Funktionen gezeichnet wird. Das hat 1. den Grund, dass der Code übersichtlicher wäre und 2. ist es so, dass beim Strom einschalten des Cockpits (d.h. Monitor von schwarz=aus auf an=Grafiken anzeigen) die Monitore nicht alle gleichzeitig an sind. Deshalb auch die Trennung.
    So wie ich die Doku richtig verstehe, geht mein Genanntes, was ich trennen möchte, mit QGraphicsScene (zusammen mit QGraphicsView)? Die meisten Grafiken müssen kontinuierlich über Zustandsänderungen des Flugzeugs (Strom, Triebwerke, Geschwindigkeit etc.) in einer "Berechnungs-App" veränderbar sein, aber das ist ein anderes Thema welches ich hier nur der Vollständigkeit halber nenne. Jetzt weißt du, was ich vorhabe ;-)


  • Lifetime Qt Champion

    @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    QScrollArea scrollArea;

    Das ist eine lokale Variable und wird zerstört sobald Konstruktor verlassen wird, kann also nicht funktionieren. Außerdem sehe ich nicht wo du scrollArea zu einem Widget/Layout hinzufügst?
    Und wieso setzt du parent as widget?!


  • Moderators

    @stefanpc81 neben den Punkten von @jsulm , die ScrollArea braucht ein QWidget was der content ist, über den man scrollen kann. z.B:

    #include <QLabel>
    #include <QScrollArea>
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QApplication app(argc, argv);
    
        QMainWindow mainWindow;
    
        mainWindow.resize(400,400);
        auto scrollArea = new QScrollArea;
        QLabel image;
        image.setPixmap(QPixmap(":/Qt_logo_2016.svg.png"));
        scrollArea->setWidget(&image);
        mainWindow.setCentralWidget(scrollArea);
    
        mainWindow.show();
    
        app.exec();
    }
    

    1c46ed32-d39d-41d5-9cd2-7f156a12c43c-image.png



  • Neben dem, was @J-Hilk und @jsulm wegen der ScrollArea angemerkt haben, wäre in dem Fall eine ScrollArea wirklich sinnvoll?!
    Man möchte in einem Cockpit (weder Simulation noch in echt) doch nicht ewig scrollen um alles ablesen zu können oder? Hängt halt alles davon ab, wie groß das alles wirklich sein soll/muss und wie groß der/die Bildschirm(e) sind :)

    Wenn man bei reinen Widgets (ohne QGraphics...) bleibt, könnte man eventuell auch QDockWidgets verwenden. Die lassen sich dann im MainWindow einzeln beliebig anordnen und verankern bzw. wieder "undocken". Dazu kann man dann einzelne Widgets im FullScreen Modus anzeigen, falls gewünscht.
    Der Nachteil wäre, dass man nicht eine homogene Oberfläche hätte (wie im Bild zu sehen), sondern es wären die einzelnen Docks zu erkennen.

    @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    desweitern möchte ich gerne, dass auf die Monitore (im Bild die beiden großen Rechtecke, insgesamt aber 4 große und ein kleinerer) nach Möglichkeit über jeweils eine eigene Klasse oder zumindest getrennt über Funktionen gezeichnet wird. Das hat 1. den Grund, dass der Code übersichtlicher wäre und 2. ist es so, dass beim Strom einschalten des Cockpits (d.h. Monitor von schwarz=aus auf an=Grafiken anzeigen) die Monitore nicht alle gleichzeitig an sind

    Das ist kein Problem. Das kann man recht einfach über Klassen (entweder QWidgets oder im Fall von QGraphicsView über QGraphicItems / QGraphicsObjects) machen.

    Es gibt schon Mehrere, die Flugzeugcockpits und die ganzen Instrumente (für RC, Simulation oder für echtes Training) in Qt nachgebaut haben... einfach mal googlen, wie die das realisiert haben. Gibt verschiedene Möglichkeiten...



  • @Pl45m4 said:

    Neben dem, was @J-Hilk und @jsulm wegen der ScrollArea angemerkt haben, wäre in dem Fall eine ScrollArea wirklich sinnvoll?!
    Man möchte in einem Cockpit (weder Simulation noch in echt) doch nicht ewig scrollen um alles ablesen zu können oder? Hängt halt alles davon ab, wie groß das alles wirklich sein soll/muss und wie groß der/die Bildschirm(e) sind :)

    Es gibt schon Mehrere, die Flugzeugcockpits und die ganzen Instrumente (für RC, Simulation oder für echtes Training) in Qt nachgebaut haben... einfach mal googlen, wie die das realisiert haben. Gibt verschiedene Möglichkeiten...

    @Pl45m4
    Sinnvoll? -> irgendwie schon. Der Text in meinem Cockpit schwankt so zw. 8 und 15 px und sollte schon lesbar sein. Die großen Monitore sind 400x400 groß. Der kleinste (CDU) nur rund 200x200. Scrollen muss man eigentlich nur, um vom oberen Teil (Overheadpanel) Eingaben machen zu können, im mittleren Teil die Monitore mehr während des Flugs sehen zu können und die unteren Teile wie bspw. der FMC-Computer (bzw. CDU) und die Schubhebel hängen eh dicht an letzterem dran.
    Der Simulator ist mehr oder weniger eh nur für mich privat. Vielleicht wäre es aber trotzdem sinnvoll, das Overheadpanel als optionales Zweit-Window ein- und auszublenden. Da der Simulator wahrscheinlich nie von meinem PC an jemand anderes wandert, ist es mir auch egal, wenn er nur mit einem "echten" Bildschirm mit der Auflösung1920x1080 pixel angezeigt werden kann...
    Und danke für den Hinweis wegen dem "googlen nach Qt-gebauten Simulatoren"!

    @jsulm @J-Hilk
    Ich dachte, man könnte die "parent als Widget" setzen, damit das GESAMTE Parent-Window der zu scrollende Inhalt wird. Ich habe jetzt verstanden, dass ich für die ScrollArea ein Objekt mit "Übergröße" angeben muss. Notfalls muss ich ein Bild mit der Hintergrundfarbe beige in der Größe 1900x2140 erstellen und so zuweisen wie von J.Hilk gezeigt.

    Vielen Dank an alle!



  • @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Ich habe jetzt verstanden, dass ich für die ScrollArea ein Objekt mit "Übergröße" angeben muss. Notfalls muss ich ein Bild mit der Hintergrundfarbe beige in der Größe 1900x2140 erstellen und so zuweisen wie von J.Hilk gezeigt.

    Muss man auch nicht unbedingt. Eine QScrollArea ist nicht anderes als ein Container für ein Widget, das größer sein KANN, nicht MUSS. Man kann auch was kleineres in eine ScrollArea packen, dann entstehen erstmal keine ScrollBars. Wenn man dann z.B. das Scaling verändert, wie beim Zoomen und der Inhalt größer wird, kann man dann die ScrollBars hinzufügen (wie bei jedem Bildverarbeitungsprogramm wenn man auf einen Bildausschnitt zoomt).

    Die QScrollArea sollte der übergeordnete Container für den/die Widgets sein, die später u.U. gescrollt werden sollen.
    Ist Graphics das MainWindow / Hauptwidget?

    Parent macht in der ScrollArea echt keinen Sinn, da das parent ja das übergeordnete Widget von Graphics ist und das willst du nicht in einen Container des "childs" packen.

    Im Prinzip so:

    • MainWindow / First Widget
      • Widgets...
      • ScrollArea
        • Scrollbare / zu große Widgets
      • noch mehr Widgets....

    Was davon was ist, ist dir überlassen und liegt eben am restlichen Programm, ob du alles in die ScrollArea packst (dann würde sich alles, was auf dem Bild zu erkennen ist als ein ganzes Element verschieben lassen) oder nur einzelne Bereiche, dass man den Bereich über den beiden Messinstrumenten runterscrollen kann und dass man dann mehr sieht, wobei die Messinstrumente dann "stehen" bleiben, da sie fest zu dem parent layout gehören und nicht Teil der scrollArea / des Scroll-Widgets sind.



  • @Pl45m4 Ist Graphics das MainWindow / Hauptwidget?
    Ja.

    Ich habe inzwischen ein einfarbiges JPG-Bild erstellt und der Code sieht nun wie folgt aus:

    main.cpp

    #include "graphics.h"
    #include <QApplication>
    #include <QLocale>
    #include <QTranslator>
    #include <QLabel>
    #include <QScrollArea>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
    
        QTranslator translator;
        const QStringList uiLanguages = QLocale::system().uiLanguages();
        for (const QString &locale : uiLanguages) {
            const QString baseName = "Widget7_" + QLocale(locale).name();
            if (translator.load(":/i18n/" + baseName)) {
                a.installTranslator(&translator);
                break;
            }
        }
        Graphics w;
        QScrollArea scrollArea;
        QLabel label;
        label.setPixmap(QPixmap("F:/PC/Programmierung mit Qt/Widget7/hintergrund.jpg"));
        scrollArea.setWidget(&label);
        w.setCentralWidget(&scrollArea);
        w.show();
        return a.exec();
    }
    

    graphics.cpp

    #include "graphics.h"
    #include "./ui_graphics.h"
    #include <QRegion>
    #include <QImage>
    
    Graphics::Graphics(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::Graphics)
    {
        ui->setupUi(this);
    }
    
    Graphics::~Graphics()
    {
        delete ui;
    }
    
    void Graphics::paintEvent(QPaintEvent *event)
    {
    //meine Grafiken mit QPainter
    }
    

    Dieses Projekt habe ich mit der Vorlage QWidgets-Anwendung mit Qt Creator erstellt. Nach dem Hinzufügen des Bildes hintergrund.jpg sind zwar die Scrollbars da und funktionieren auch, jedoch verdeckt diese jetzt die ganzen Grafiken (siehe graphics.cpp). Was nun?
    Was mich bei dieser Projektvorlage stört, ist, dass ich offensichtlich kein "QMainWindow mywindow" o.ä. sehe bzw. erstellen kann. Macht ja keinen Sinn, denn das Fenster wurde ja automatisch vom Qt Creator erstellt.
    Eure Beitragsbeispiele sehen so aus, als ob sie manuell nach dem Erstellen eines leeren Projekts geschrieben wurden, richtig?

    @Pl45m4 schrieb:
    MainWindow / First Widget
    Widgets...
    ScrollArea
    Scrollbare / zu große Widgets
    noch mehr Widgets....

    Diese Struktur würde ich gerne versuchen anzuwenden, jedoch steht mir die o.g. Vorlage QWidgets-Anwendung im Weg, wenn du verstehst, was ich meine?



  • @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Dieses Projekt habe ich mit der Vorlage QWidgets-Anwendung mit Qt Creator erstellt. Nach dem Hinzufügen des Bildes hintergrund.jpg sind zwar die Scrollbars da und funktionieren auch, jedoch verdeckt diese jetzt die ganzen Grafiken (siehe graphics.cpp). Was nun?

    Weil eine ScrollArea i.d.R. nur ein Widget enthalten kann. Wenn du das Label mit dem Bild als Widget der ScrollArea hinzufügst, expandiert das Bild in dem Bereich (je nach sizePolicy etc) und kann dann mit den ScrollBars hin- und hergeschoben werden. Um mehrere Elemente in einer ScrollArea zu haben, muss man diese einem Widget (mit Layout) hinzufügen und dann das gesamte Widget wiederum an die ScrollArea übergeben... aber auch dann wird das GESAMTE Widget gescrollt...

    @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Was mich bei dieser Projektvorlage stört, ist, dass ich offensichtlich kein "QMainWindow mywindow" o.ä. sehe bzw. erstellen kann. Macht ja keinen Sinn, denn das Fenster wurde ja automatisch vom Qt Creator erstellt.

    Wahrscheinlich hast du bei der Erstellung des Projekts im Wizard "Graphics" als Namen für das MainWindow angegeben. Graphics ist ja sogar ein abgeleitetes QMainWindow
    Siehe hier:

    Graphics::Graphics(QWidget *parent)
    : QMainWindow(parent)

    @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Eure Beitragsbeispiele sehen so aus, als ob sie manuell nach dem Erstellen eines leeren Projekts geschrieben wurden, richtig?

    Das Beispiel von @J-Hilk scheint aus irgendeinem Qt Example zu sein. Da passiert aber auch nichts magisches...

    Wenn man ein neues Projekt einer QWidget-Anwendung mit einem QMainWindow erstellt, macht man eigentlich nichts falsch.

    Die ScrollArea und alles andere könnte man auch über den DesignMode in der Graphics.ui Datei konfigurieren. So spart man sich das Erstellen der ganzen Sachen in der main() bzw. im Code der Klasse selbst. Kann man nutzen, muss man aber nicht. Einiges geht eben leider (manchmal auch "zum Glück") nicht im QtDesigner...

    @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Diese Struktur würde ich gerne versuchen anzuwenden, jedoch steht mir die o.g. Vorlage QWidgets-Anwendung im Weg, wenn du verstehst, was ich meine?

    Nee, ehrlich gesagt nicht :D
    Was hält dich davon ab in QtCreator auf das Projekt zu rechtsklicken und ne neue Qt GUI / C++ Klasse hinzuzufügen?
    Jede "Vorlage" kann beliebig verändert werden. Selbst im Code der offiziellen Qt Examples kann man rumpfuschen :D Aber dann sollte man aufpassen, da man dann seine lokale Version des Example Projekts permanent verändert (außer man installliert Qt neu) -> Eventuell dann Kopie anlegen bzw. als neues Projekt speichern.



  • Ich habe jetzt mal näher in Betracht gezogen QGraphicsScene und QGraphicsView zu benutzen.

    @Pl45m4 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Um mehrere Elemente in einer ScrollArea zu haben, muss man diese einem Widget (mit Layout) hinzufügen und dann das gesamte Widget wiederum an die ScrollArea übergeben... aber auch dann wird das GESAMTE Widget gescrollt...

    Es ist so gewollt, dass das GESAMTE Widget gescrolt wird. Das QLabel kommt mir nicht als passend vor (nur Bild oder Text als Inhalt). Kann ich ein vertikales Layout erzeugen OHNE den Designer von "mainwindow.ui" (hier neues Projekt, neuer Name) zu verwenden? Es ist nämlich so, wenn ich den Designer verwende, dass ich dann in meiner main.cpp keinen Zugriff auf den von mir bei "objectname" eingetragenen Namen "mywidget" bekomme. z.B.:

    MainWindow w;
    QScrollArea scrollArea;
    scrollArea.setWidget(&mywidget);
    w.setCentralWidget(&scrollArea);
    w.show();
    

    Ich suche ein Layout, welches die volle Größe 1900x2140px haben soll und auf dem es sich zeichnen lässt (mit QGraphicsScene/QGraphicsView). Welches Layout würdest du mir empfehlen bzw. wie muss ich diesen Code anpassen, damit es funktioniert?



  • @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Kann ich ein vertikales Layout erzeugen OHNE den Designer von "mainwindow.ui" (hier neues Projekt, neuer Name) zu verwenden?

    Layouts sind wie alles andere auch nur Klassen, von denen mal eine Instanz erstellen kann, um sie dann zu nutzen.

    Es ist nämlich so, wenn ich den Designer verwende, dass ich dann in meiner main.cpp keinen Zugriff auf den von mir bei "objectname" eingetragenen Namen "mywidget" bekomme.

    Das macht man ja auch nicht in der main(). Kannst das Layout auch in der Klasse selbst bearbeiten.
    Nur eben nicht dem ScrollArea Widget das parent übergeben, in dem es sich befindet :)
    Sonst kann man das meiste (je nach Programm) in den jeweiligen Widget-Klassen designen und coden.

    @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Ich suche ein Layout, welches die volle Größe 1900x2140px haben soll und auf dem es sich zeichnen lässt (mit QGraphicsScene/QGraphicsView). Welches Layout würdest du mir empfehlen bzw. wie muss ich diesen Code anpassen, damit es funktioniert?

    Layouts sind dazu da andere funktionale Widgets zu organisieren und ihr Resize Verhalten usw. zu regeln. Andere Sachen "kann" ein Layout nicht, das machen die Dinge, die sich in dem Layout befinden.
    In einer QGraphicsScene kann man immer zeichnen bzw. grafische Objekte erzeugen. Die Größe der "Scene" kannst du auch anpassen. Und falls die Szene über die QGraphicsView (die "Leinwand") hinaus geht, lässt es sich auch scrollen, ohne zusätzliche ScrollArea (die View hat ihre eigene).



  • Ich habe festgestellt, dass ich mit dem Code über QPainter besser zurecht komme, als mit QGraphicsScene und was dazu passt. Ich habe es jetzt mit den Scrollbars so gemacht wie von @J-Hilk beschrieben, also in main.cpp

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
    
        QLabel* imageLabel = new QLabel;
        QImage image1(":/MainWindow/hintergrund.jpg");;
        imageLabel->setPixmap(QPixmap::fromImage(image1));
        QScrollArea* scrollArea = new QScrollArea;
        scrollArea->setWidget(imageLabel);
        w.setCentralWidget(scrollArea);
        w.show();
    
        return a.exec();
    }
    

    Die Scrollbars lassen sich bewegen und das Fenster zeigt mein einfarbiges Bild als Hintergrund an. Mein Problem ist jetzt, dass ich darüber mit QPainter zeichnen will und es nicht angezeigt bekomme. Wenn ich den Code vom Bild ausblende, erscheint der zu zeichnende Bereich, aber mit Standard-weißem Hintergrund und ohne Scrollbars. Code von MainWindow.cpp

    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
    {
        ui.setupUi(this);  
    }
    
    void MainWindow::paintEvent(QPaintEvent* event)
    {
        QPainter painter;
        painter.begin(this);
        painter.setPen(MyColor::black);
        painter.drawLine(525, 5, 525, 535);
    ...
    
        painter.end();
    
    }
    

    Mir ist klar, dass ich entweder painter.begin(this); das this ersetzen muss, oder aber gleich eine (oder mehrere) eigene Klasse(n) zum Zeichnen (viele Objekte!) bereitstellen kann. Leider habe ich es selbst nicht hinbekommen und im Web nichts passendes gefunden und hoffe auf eine Lösung von euch. Ich bin dankbar für jede Hilfe! MyColor stellt übrigens eigene statische QColor Farben bereit, das habe ich zum Glück zum Laufen gebracht.



  • @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    Mein Problem ist jetzt, dass ich darüber mit QPainter zeichnen will und es nicht angezeigt bekomme. Wenn ich den Code vom Bild ausblende, erscheint der zu zeichnende Bereich, aber mit Standard-weißem Hintergrund und ohne Scrollbars

    Doch bekommst du definitiv... Das Problem ist, du paintest auf dem MainWindow und somit auch in dessen Koordinatensystem. Der vertikale Strich, den das paintEvent produziert, landet bei mir irgendwo auf Höhe der ToolBar (dort sieht man ein Stück, vorrausgesetzt die sitzt oben) und würde gerade heruntergehen, wenn er nicht von dem centralWidget (der ScrollArea) verdeckt werden würde.

    Nur zur Demo:
    Probier w.setCentralWidget(nullptr); vor w.show() und du wirst sehen, dass die Linie direkt auf das MainWindow Widget gemalt wird.
    Ungefähr so:
    (Der rote Bereich ist der Bereich, der normalerweise vom centralWidget verdeckt wird)
    MainW_painter.png

    Hab mal ein kleines Beispiel gebastelt, wie ich wahrscheinlich vorgehen würde, wenn ich es mit paintEvents machen müsste :)
    Würde sonst eher zur QGraphicsView greifen.

    Die main komplett standard
    (ich versuch meist die main so clean wie möglich zu halten und nur generelle und grundlegende Einstellungen / Anpassungen, die die gesamte QApp oder alle Widgets betreffen sollen dort vorzunehmen)

    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    MainWindow header

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <mywidget.h>
    
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    
    private:
        Ui::MainWindow *ui;
    
        MyWidget* m_canvas;
    
    };
    
    #endif // MAINWINDOW_H
    

    MainWindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    #include <mywidget.h>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow),
        m_canvas(new MyWidget)
    {
        ui->setupUi(this);
    
        m_canvas->setGeometry(0, 0, 800, 600);
        QScrollArea *scrollArea = new QScrollArea;
        scrollArea->setWidget(m_canvas);
        setCentralWidget(scrollArea);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    Neues, "blankes" Widget.
    Auf dem später gezeichnet wird und welches sich dann in dem scrollbaren Bereich befinden soll.

    #ifndef MYWIDGET_H
    #define MYWIDGET_H
    
    #include <QWidget>
    
    namespace Ui {
    class MyWidget;
    }
    
    class MyWidget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit MyWidget(QWidget *parent = nullptr);
        ~MyWidget();
    
        void paintEvent(QPaintEvent *ev);
    
    private:
        Ui::MyWidget *ui;
    };
    
    #endif // MYWIDGET_H
    

    Widget Code

    #include "mywidget.h"
    #include "ui_mywidget.h"
    #include <QPainter>
    
    MyWidget::MyWidget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::MyWidget)
    {
        ui->setupUi(this);
    
    
    
    }
    
    MyWidget::~MyWidget()
    {
        delete ui;
    }
    
    
    void MyWidget::paintEvent(QPaintEvent* ev)
    {
        QPainter painter;
        painter.begin(this);
        painter.setPen(QPen(Qt::black, 5));
        painter.drawLine(10, 5, 100, 250);
        painter.drawEllipse(250, 50, 125, 300);
        painter.drawLine(250, 50, 125, 300);
        painter.drawRect(550, 200, 200, 350);
    
        painter.end();
    
    }
    

    Auf dem Widget kann nun beliebig gezeichnet werden. Die Größe hab ich beim Erstellen des Widgets im MainWindow auf 800x600 gestellt (zum Test, damit ScrollBars erscheinen).
    Das centralWidget des MainWindows is aktuell nur die QScrollArea, in der sich wiederum das "Zeichen-Widget" befindet. Lässt sich aber auch anpassen und durch ein Layout ersetzen. Dann hätte man auch Platz für Buttons usw. außerhalb der ScrollArea und des Zeichenbereichs

    Sieht dann ungefähr so aus:
    (Den Hintergrund kann man natürlich auch einfarbig färben. Das müsste sogar mit allein StyleSheet gehen.)

    MainW_WidgetPainter.png

    @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    MyColor stellt übrigens eigene statische QColor Farben bereit, das habe ich zum Glück zum Laufen gebracht.

    Qt::black hätte es auch getan :)
    Falls sowas Probleme bereitet, würde ich mich nochmal genauer mit C++ Grundlagen beschäftigen bzw. das Wissen auffrischen. Denn das was danach noch für dein "Hobby"-Projekt kommen wird, wird mit Sicherheit nicht einfacher :)



  • @Pl45m4 Danke für den ausführlichen Code! Leider spuckt dann VS2019 noch 6 Fehlermeldungen aus, die alle mit dem "Ui" zu tun haben. Im Detail:
    PaintND.cpp

    PaintND::PaintND(QWidget* parent) :
    	QWidget(parent),
    	ui(new Ui::PaintND)
    {
    	ui->setupUi(this);
    }
    

    E0393 Der Typ eines Zeigers auf eine unvollständige Klasse ("Ui::PaintND") ist nicht zulässig.
    E0070 Ein unvollständiger Typ ist nicht zulässig.
    (2x) -> C2027 Verwendung des undefinierten Typs "Ui::PaintND"

    und in MainWindow.cpp

    MainWindow::MainWindow(QWidget* parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow),
        nd_canvas(new PaintND)
    {
        ui->setupUi(this);
        nd_canvas->setGeometry(0,0,1900,2140);
        QScrollArea* scrollArea = new QScrollArea;
        scrollArea->setWidget(nd_canvas);
        setCentralWidget(scrollArea);
    }
    

    (2x) -> C2027 Verwendung des undefinierten Typs "Ui::MainWindow"

    Im Web steht nur sehr wenig dazu und konnte leider nichts passendes dazu finden.

    PS: Habe MyWidget in PaintND umbenannt und m_canvas in nd_canvas umbenant

    1. Edit: #include <mywidget.h> hatte ich bereits durch #include "mywidget.h" bzw. #include "PaintND.h" korrigiert (2x).
    2. Edit: Und an der Stelle (Widget code bzw. PaintND.cpp schreibst du #include "ui_mywidget.h" -> das habe ich auf #include "ui_MainWindow.h" geändert, ein ui_mywidget.h gibt es nämlich nciht bei mir.


  • @stefanpc81 said in Wie unter Qt Widget-Anwendung größerer Inhalt als angezeigtes Fenster?:

    ein ui_mywidget.h gibt es nämlich nciht bei mir.

    Ja das wird der Fehler sein. Habe MyWidget als Qt Klasse mit UI Form angelegt (auch wenn man es aktuell wahrscheinlich nicht benötigt).
    Durch die versuchten Zugriffe auf die UI entstehen bei dir die Fehler.

    Du kannst alles was in PaintND mit UI::.... oder ui-> beginnt einfach löschen.

    Das m_..... signalisiert nur dass die nachfolgende Variable eine Membervariable einer Klasse ist.
    Das ist reine Namenskonvention und soll nur die Lesbarkeit bzw. das Verständnis des Codes erleichtern.
    Einige machen _test, andere m_test oder test_ oder mTest...
    Irgendwas davon zu nutzen kann ich nur empfehlen, da man so bei zig hundert Variablen besser unterscheiden kann, was lokale sind und welche zu einer Klasse gehören und somit durchgehend verfügbar sind.
    Zudem zeigt dir die Auto-Vervollständigung bei z.B. m_ oder _ direkt alle Member an, da sie ja dann alle so beginnen.

    Edit:

    Die ui_MainWindow.h in PaintND einzubinden ist nicht so clever :)
    Das soll ja die UI Form Klasse bzw. der compilierte Header von MainWindow sein. Klassen sollten keinen direkten Zugriff auf die UI einer anderen Klasse haben.
    Wenn du auch keine MainWindow.ui nutzt / hast, kann ALLES (auch in MainWindow) mit ui erstmal weg...
    Dann musst du aber jedes Widget später manuell im Code hinzufügen.
    Das Nutzen des QtDesigners und einer UI Datei macht einiges leichter. Coden muss man ja so oder so.



  • Vielen Dank, es funktioniert endlich! Ich musste allerdings ein neues Projekt erstellen, da ich mit den Änderungen nicht mehr klar kam (bzw. ohne Fehlermeldungen), einmal beim Kopieren die Anpassung vergessen hatte und festgestellt habe, dass ich mit dem Ui / ui nicht "MainWindow" sondern "MainWindowClass" verwenden muss...



  • @stefanpc81

    Super. Markier am besten noch das Thema über die Themeneinstellungen als "gelöst".


Log in to reply