Qt Rysowanie QPainter obiekty.

0

Witam

Zaczynam swą przygodę z rysowaniem w QT. Nie potrafię jednak umieścić osobno narysowanych obiektów (dwie inne klasy) w tym samym oknie.
Chciałem zacząć naukę od banału. Jednym obiektem będzie Oś XY, a drugim jakaś tam linia na tej osi. O ile oś XY się rysuje to lini już nie widać, choć kompilacja bez błędna.

Klasa mainwindow

#include "os.h"
#include "linia.h"
#include <QMainWindow>
#include <QPainter>
#include <QWidget>
#include <QPushButton>


class Os;
class linia;
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow();
    Os *obiekt;
    linia *li;
    void ustokna();

};

/***************cpp***************/
MainWindow::MainWindow()
{

    ustokna();
    obiekt = new Os();
    li = new linia(obiekt);
    setCentralWidget(obiekt);

}

void MainWindow::ustokna()
{
    setFixedSize(300,300);

}

Klasa osi XY

#include <QObject>
#include <QPainter>
#include <QDebug>
#include <QFont>

#define q qDebug()

class MainWindow;
class Os : public QWidget
{
    Q_OBJECT
public:
        static int x;
        static int y;
        Os();
        Os(MainWindow *parent);
        void paintEvent(QPaintEvent*);
private:
        MainWindow *parent;
        QPainter *xy;
};

/********************cpp*************/
Os::Os(MainWindow*parent ): QWidget(parent)
{}
Os::Os()
{}
void Os::paintEvent(QPaintEvent*)
{
    QFont sf("Times", 16, QFont::Bold);

    xy = new QPainter(this);
    xy-> setPen(Qt::blue);

    xy-> drawLine(150,300,150,80);
    xy-> drawLine(0,170,  300, 170);
    xy-> setPen(Qt::red);
    xy-> setFont(sf);
    xy-> drawText(260, 165 ,"X");
    xy-> drawText(160, 100, "Y");
    xy-> end();
}
int Os::x = 150;
int Os::y = 170;

klasa lini

#include "mainwindow.h"
#include <QWidget>
#include <QPainter>
#include <QDebug>

#define q qDebug()


class MainWindow;
class Os;

class linia : public QWidget
{
    Q_OBJECT
public:

        int czynnik;
        QPainter *lin;
        linia(Os*parent);
        void paintEvent(QPaintEvent*);
};

/*********************cpp******************/
#include "linia.h"

linia::linia(Os *parent): QWidget(parent)
{}

void linia::paintEvent(QPaintEvent *)
{

    lin = new QPainter(this);
    lin-> setPen(Qt::red);
    lin-> drawLine(150, 150,  150, 180);
    lin-> end();

}

dodanie znaczników <code class="cpp"> - Furious Programming

0

Bo robisz to ŹLE!
To zawsze powinno wyglądać tak:

void twojWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

     painter.setBrush(palette().brush(QPalette::Normal, QPalette::WindowText));

     QRect r = rect();
     painter.drawLine(r.bottomLeft(), r.topRight());
     ...
}

QPainter jest tworzony TYLKO na czas paintEvent i TYLKO do rysowania SWOJEJ zawartości.
Oba twoje widgety powinny obsługiwać paintEvent.

Na dodatek nie ustawiasz rozmiaru li, jeśli dobrze pamiętam to uzyskasz wtedy domyślny rozmiar odpowiadający sizeHint, a jego domyślna wartość to (50,50). W takim kwadracie twoja linia się nie mieści. Lepiej uzależnij rysowaną zawartość od rozmiaru widgeta.

0

Oba twoje widgety powinny obsługiwać paintEvent.

Więc jak ? Obie klasy mają korzystać z jednego pantEvent ? mam ją zrobić statyczną ? Nie bardzo rozumiem jak to zaimplementować :(? to przecież zrobiłem

void linia::paintEvent(QPaintEvent *)
void Os::paintEvent(QPaintEvent*)

dwie klasy dziedziczące po QWidget mają paintEvent.

0

Faktycznie, działa. Jeśli w klasie lini wpisałem
this->resize(300, 300)
Linia pokazała się cała. Z tego co pamiętam i teraz próbuje to, żeby uzależnić wielkość widżetu od jego zawartości całość musi być w jakimś layout, bo inaczej nie działa QSizePolicy, a wsadzając oś i linie do layout muszą one być poukładane zgodnie z siatką, a to spowoduje, że linia nie będzie chciała zachodzić na oś. Najestetyczniej byłoby to wszystko umieścić w QGroupBox. Na razie próbuje i nie mam do przedstawienia, żadnego dyskusyjnego kodu mam jednak nadzieję ,że prędzej ukaże się tutaj sposób niż moje rozwiązanie.

0

Jeśli chcesz minimalizować ilość kodu to layout jest dobrym rozwiązaniem. Poprawiając twój kod:

MainWindow::MainWindow()
{
    ustokna(); // nie mam pojęcia czemu ci to służy

    obiekt = new Os();
    setCentralWidget(obiekt);

    QBoxLayout *layout = new QHBoxLayout(obiekt);
    li = new linia;
    layout->addWidget(li);
    layout->setContentsMargins(0,0,0,0);
}
0

Twój sposób się nie kompiluje. Nie ma tak przeładowanego konstruktora QBoxlayout jaki podałeś, ponieważ potrzebuje on jeszcze parametru direct, a dalej *QWidget.

QBoxLayout(Direction dir, QWidget * parent = 0
enum Direction { LeftToRight, RightToLeft, TopToBottom, BottomToTop })

Zrobiłem tak jak poniżej. Kompiluje się, ale widać kawałek lini tylko.
Z logiką działania: Umieszczam QBoxLayout w mainwindow -> do QBoxlayout dodaje kolejne widgety.

   obiekt = new Os(this);
        li = new linia(this);
        //setCentralWidget(obiekt);
        QBoxLayout *layout = new QBoxLayout(QBoxLayout::LeftToRight, this);
        layout->addWidget(obiekt);
        layout->addWidget(li);
        layout->setContentsMargins(0,0,0,0);

edit:
ustokna
To moja fanaberia :) Funkcja do której wrzucam wszystkie ustawienia mające dotyczyć głównego okna, rozmiar, marginesy, kolor blabla...

dodanie znaczników <code class="cpp"> - Furious Programming

0

Działa. Poprawiłem na:

obiekt = new Os(this);
        li = new linia(this);
        setCentralWidget(obiekt);
        hb = new QHBoxLayout(obiekt);
        hb->addWidget(li);
        hb->setContentsMargins(0,0,0,0);

Dziękuję za pomoc w temacie :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1