Zastosowanie suwaków do przesUwania obrazu, który się nie mieści w oknie

0

Witam, chciałbym poprosić o pomoc w następującej sprawie.

Nie wiem co mam zrobić, aby można było korzystać z suwaków, gdy obraz jest większy od okna, w którym jest wyświetlany. Wyświetlam obraz w następujący sposób. Stworzyłem klasę Image, której rodzicem jest QWidget. Image posiada funkcję void paintEvent. W tej funkcji tworzę obiekt QImage. W pętli za pomocą funkcji QImage - setpixel tworzę obraz, który następnie rysuję wykorzystując funkcję QPainter - drawImage. W mainwindow tworzę obiekt klasy Image oraz QVBoxLayout, do którego dodaje stworzony prze ze mnie widget Image. Próbowałem wykorzystać klasę QScrollArea, w ten sposób:

 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    im=new Image();
    QVBoxLayout *l=new QVBoxLayout(this->ui->graphicsView);
    l->addWidget(im);
   
    connect(ui->actionPowieksz,SIGNAL(triggered()),this,SLOT(powie()));
    connect(ui->actionPomniejsz,SIGNAL(triggered()),this,SLOT(pomn()));
    connect(ui->actionOdswiez,SIGNAL(triggered()),this,SLOT(odsw()));
    connect(ui->actionOtw_rz,SIGNAL(triggered()),this,SLOT(open()));
    im->start=1;

    scrollArea = new QScrollArea;
    scrollArea->setBackgroundRole(QPalette::Dark);
    scrollArea->setWidget(im);
}

Jednak wtedy nic się nie wyświetla. Próbowałem też po prostu rysować w graphicsView, który ma w sobie suwaki, ale są nieaktywne, gdy rysowany obraz nie mieści się.

Pozdrawiam

0

Hm...graphics view wyrzuć,on do wyświetlania obrazków ci niepotrzebny.Ustaw scroll areę jako central widget okna,i upewnij się,że ten image co wrzucasz w scroll areę jest dobry(tzn jakieś im->isValid() daje true).I nie ma siły,żeby takie coś nie zadziałało.

0

Niestety, ale gdy rysuje obraz w scrollArea, suwaki też nie działają. Poza tym, klasa QImage nie ma metody isValid().

0

Cóż,na moje oko tworzysz QImage który nie zawiera w sobie nic.Spróbuj testowo zbudować go z pliku z grafiką,i dopiero wrzucaj do scrollArea.

0

Według mnie pierwszy problem to twój widget? Przetestowałeś go? Działa ten twój Image?
Dopiero jak to zweryfikujesz możesz brać się za narzekanie na QScrollArea (lub pokaż jak to zrobiłeś).
(QGraphicsView bym na razie nie używał, za dużo tam trzeba robić samemu, a jeśli już to lepiej skorzystać z QML-a).

0

Sprawdzałem, mój QImage działa, wyświetlał się w polach, które testowałem. Spróbowałem też wczytać gotowy obraz BMP, ale wtedy również nie działały suwaki. Może w moim sposobie rysowania jest jakiś błąd?

 
void Image::paintEvent(QPaintEvent *)
{
    if(wczytaj==1)
    {
        mac.wczytaj();
        delete image;
        image=new QImage(mac.wie,mac.kol,QImage::Format_ARGB32);

        wczytaj=0;
        start=1;
        update();

    }
//    QString blabla = "obraz.bmp";
//    image->load(blabla,0);

    QPainter paint(this);
    paint.drawImage(0,0,*image);
    QRgb value1;

    int wys, szer;

    if(start==1)
    {
        for(int i=0;i<mac.wie;i++)
        {
            for(int j=0;j<mac.kol;j++)
            {
                int x=mac.tab2[i][j];
                value1=mac.value[j];
                image->setPixel(j,i,value1);
            }
        }
        *kopia=*image;
        start=0;
    }

    if(pocz==1)
    {
        *image=*kopia;
        update();
        pocz=0;
    }

    if(pow==1)
    {
        QImage* tempimage = new QImage;
        szer=1.25*(image->width());
        wys=1.25*(image->height());
        *tempimage=image->scaled(szer,wys,Qt::KeepAspectRatio,Qt::FastTransformation);
        *image=*tempimage;
        update();

        pow=0;
        pocz=0;
        delete tempimage;
    }

    if(pom==1)
    {
        QImage* tempimage = new QImage;
        szer=0.8*(image->width());
        wys=0.8*(image->height());
        *tempimage=image->scaled(szer,wys,Qt::KeepAspectRatio,Qt::FastTransformation);
        *image=*tempimage;
        update();

        pom=0;
        pocz=0;
        delete tempimage;
    }

}
0

A weź zbadaj,co otrzymujesz w wyniku Image::size()?Ponadto upewnij się,że QScrollArea ma ustawione widgetResizable na false.

0

Lista błędów dużych błędów:

  1. wczytywanie w paintEvent (w szczególnych przypadkach jest to praktykowane, ale zdecydowanie twój przypadek pod to nie podpada)
  2. NIGDY nie wywołuj update w paintEvent

Ogólnie paintEvent ma robić tylko to co sama nazwa wskazuje: RYSOWAĆ, każde inne operacje w tej metodzie muszą mieć jedynie postać incydentalną (jeśli jesteś początkujący to raczej nie powinieneś natknąć się na taki przypadek).

Napisz co ma robić ten widget (albo jeszcze lepiej ogólnie co chcesz zrobić, może widget nie ejst potrzebny), to może pokaże ci jak to powinno wyglądać.

0

A weź zbadaj,co otrzymujesz w wyniku Image::size()?Ponadto upewnij się,że QScrollArea ma ustawione widgetResizable na false.

Image::size() zwraca rozmiary zrobionego przeze mnie obrazka i to się zgadza. Próbowałem w QScrollArea z ustawionym widgetResizable na false i true i było to samo.

Lista błędów dużych błędów:

  1. wczytywanie w paintEvent (w szczególnych przypadkach jest to praktykowane, ale zdecydowanie twój przypadek pod to nie podpada)
  2. NIGDY nie wywołuj update w paintEvent

Ogólnie paintEvent ma robić tylko to co sama nazwa wskazuje: RYSOWAĆ, każde inne operacje w tej metodzie muszą mieć jedynie postać incydentalną (jeśli jesteś początkujący to raczej nie powinieneś natknąć się na taki przypadek).

Napisz co ma robić ten widget to może pokaże ci jak to powinno wyglądać.

Spróbowałem też w konstruktorze wczytać gotowy obraz z dysku i wyświetlić go na scrollArea za pomocą QPainter::drawImage w paintEvent. Niestety wtedy też suwaki nie działają. Mój widget posiada obiekt mac mojej klasy Macierz. Metoda wczytaj pobiera dane z pliku txt i zapisuje je w dynamicznej dwuwymiarowej tablicy. Następnie w paintEvent rysuje piksel po pikselu. Kolor jest zależny od wartości liczby z dwuwymiarowej tablicy. W zasadzie to działa tylko mam problem z suwakami. Ewentualnie zrobię tak jak w tym przykładzie http://doc.trolltech.com/4.5/widgets-imageviewer.html tzn. stworzę QScrollArea, którego dzieckiem będzie QLabel i w QLabel umieszcze mój QImage za pomocą QLabel::setPixmap.

0

wystarczy spojrzeć na opis QSrollArea i wiać, że to można zrobić prościej (bez własnego widget-a)

0

Jednak chyba będę musiał pozostać przy swoim widget'cie. Oprócz samego wyświetlenia obrazu muszę zrobić jeszcze osie, ponieważ obraz jest wykresem płaskim. W związku z tym mam pytanie. Jeśli chciałbym, aby oś pozioma znajdowała się pod wykresem a pionowa po jego lewej stronie, muszę stworzyć dwa kolejne widgety, które będą wyświetlane w oddzielnych obiektach na formularzu?

0

Nie.Skoro i tak bawisz się paintEventem,to najprościej będzie jak domalujesz je sobie sam

0

ja bym robił osobno, z prostej przyczyny. Obrazek umieścić w scroll area osie obok i gdy scroll area zmienia pozycję uaktualniać osie.
Warto się by było nawet zastanowić czy osiami nie zastąpić scroll bar-ów.

Wracając do problemu ze scroll area i rozmiarem zawartości.
Najwyraźniej twój widget nie zwraca właściwego rozmiaru. Nie zwraca właściwego sizeHint (preferowany rozmiar).

Nadal uważam, że możesz bez problemu stosować QLabel.
Kod generujący obrazek mógłby emitować sygnał z QPixmap, który byś połączył ze slotem QLabel::setPixmap (QPixmap::fromImage).

0

Przepraszam, że dopiero teraz piszę, ale wcześniej nie maiłem czasu, żeby zająć się programem. Osie zrobiłem tak, że to są oddzielne obiekty, które wyświetlam i mogę je powiększać i pomniejszać tak jak wykres. Jak się zmienia wielkość wykresu to aktualizuje pozycje osi tak, aby były cały czas przy wykresie. Jednak przez to mam problem ,kiedy używam zoom moje widgety mogą być ucinane na formularzu. W jaki sposób można ustawić suwaki w oknie głównym?

edit

Już wiem jak można dodać suwaki do okna głównego. Na formularzu umieściłem frame i włożyłem do jego wszystkie moje widgety. W konstruktorze MainWindow stworzyłem QScrollArea i wywołałem metodę QScrollArea::setWidget.

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QScrollArea *scrollArea;
    scrollArea = new QScrollArea;
    this->setCentralWidget(scrollArea);
    scrollArea->setWidget(this->ui->frame);
...
...
...
 

Jednak teraz program ma problemy z odświeżaniem, np. gdy do wykresu dodam siatkę (to jest oddzielny obiekt, który wyświetlam na wykresie), to gdy wybieram opcję usuń siatkę nic się nie dzieje do pÓÓÓÓki ręcznie nie odświeżę okna np. poprzez maksymalizację. W celu odświeżania tego co wyświetlam używam funkcji update() i zanim dodałem frame to działało, nie musiałem ręcznie odświeżać okna. Jest na to jakieś rozwiązanie?

edit2

Z tego co zobaczyłem teraz odświeżanie następuje tylko wtedy gdy jakiś widget zmienia swój rozmiar. Np. gdy mam otwarty jakiś wykres i otwieram inny, to gdy ma taki sam rozmiar wtedy nic się nie dzieje, a gdy ma inny to się od razu odświeża i wyświetla nowy.

0

Użyj Bracie viewport()->update() zamiast update()

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