"Segmentation fault" po wczytaniu obrazka

2014-08-15 11:20
0

Hej ;).

Po długim czasie zabrałem się za painta. Wszystko ok, tylko mam problem z wczytaniem obrazu do programu.

Podczas wczytania obrazu:

-obraz pojawia się, ale nie można po nim rysować.
-Zbyt duży obraz zamyka program.

Podczas wczytywania obrazu, ale po kliknięciu ,,anuluj":

-następuje jakby ,,wyczyszczenie utworzonych obiektów"

QPainter jakby nie istniał, QPixmap również.

Wklejam kod. Proszę o nie ocenianie konstrukcji tego programu. To na razie projekt.

MainWindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
#include <QMessageBox>
#include <QMouseEvent>
#include <QLabel>
#include <QDesktopWidget>
#include <QMenu>
#include <QMenuBar>
#include <QFile>
#include <QFileDialog>
#include <QString>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
   void paintEvent(QPaintEvent *e);
   void mousePressEvent(QMouseEvent *e);

    QPixmap *map ;
    QLabel *tabelka;
    QAction *quit;
    QPainter *pi;

private:

  int x,y,x1,y1;
  bool check;
  QString xdd;
  QFileDialog *dialog;
private slots:
  void save();
  void open();

};

#endif // MAINWINDOW_H

MainWindow.cpp


#include "mainwindow.h"

#define test QMessageBox::about(this,"test","test");

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    check = true; // to draving.

    map = new QPixmap (this->width(),this->height()); //some size.
    tabelka = new QLabel;
    pi = new QPainter (map);

    map->fill(); //set white theme.

    QPen *pen = new QPen(Qt::black,2);
    pi->setPen(*pen);

    tabelka->setPixmap(*map);
    this->setCentralWidget(tabelka);

    QAction *openn = new QAction ("open",this);
    quit = new QAction ("&Quit",this);
    QAction *savee = new QAction ("Save", this);
    QMenu *file;
    file = menuBar()->addMenu("&File");
    file->addAction(quit);
    file->addAction(savee);
    file->addAction(openn);

    connect(quit,SIGNAL(triggered()),this, SLOT(close()));
    connect (savee,SIGNAL(triggered()),this,SLOT(save()));
    connect (openn,SIGNAL(triggered()),this,SLOT(open()));

       //25 - 38 simple, menu connection.

}

MainWindow::~MainWindow()
{

}

void MainWindow::paintEvent(QPaintEvent *e)
{

}

void MainWindow::mousePressEvent(QMouseEvent *e)
{
if(e->button()== Qt::LeftButton)
  {
   if(check)
   {

      x = e->x();
      y = e->y();
      check = false;

   }
    else if (!check)
   {

   x1 = e->x();
   y1 = e->y();
   check = true;

   pi->drawLine(x,y,x1,y1); // !!!!!!!!!!!!!!!!!!!!!!! Błąd jest tutaj, ale nie wiem co z tym zrobić. Dlaczego to ,,krzaczy".

   tabelka->setPixmap(*map);

   //simple, test draving.

   }

  }

}

void MainWindow::save() //saving. It is fine.
{
   dialog = new QFileDialog (this);

  xdd = dialog->getSaveFileName(this,"Save","/home/","Images(*.png)");

    QFile file(xdd);
    file.open(QIODevice::WriteOnly);
    map->save(&file,"png");

}
void MainWindow::open()
{
   dialog = new QFileDialog (this);
   xdd = dialog->getOpenFileName(this,"Open","/home/","Images(*.png)"); //working on linux

 map->load(xdd);
 tabelka->setPixmap(*map); //to show up.

}

Main.cpp


#include "mainwindow.h"
#include <QApplication>
#include <QLabel>
#include <QPainter>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.setGeometry(0,0,500,500);
    w.show();
    return a.exec();
}

Proszę o wytłumaczenie, co i jak.

Błąd to: Seg.entation fault.

Dzięki wielkie ;)

Nie używaj prefiksów/sufiksów w tytułach wątków - od tego są tagi; - furious programming 2014-08-15 15:11

Pozostało 580 znaków

2014-08-15 13:23
1
pi->drawLine(x,y,x1,y1); // !!!!!!!!!!!!!!!!!!!!!!! Błąd jest tutaj, ale nie wiem co z tym zrobić. Dlaczego to ,,krzaczy".

wyświetl sobie ile wynoszą te współrzędne i czy pi nie jest nullem.
czy wartości są sensowne?

współrzędne są logiczne: położenie myszki przy kliknięciu. Nie mogę sprawdzić, czy jest nullem. if (!pi) nie działa. - Kenzy1 2014-08-15 13:44
a kto cię tak nauczył sprawdzania nulla? if (pi!=nullptr) - Azarien 2014-08-15 14:31
skoro da się ustawić wskaźnik na 0, lub NULL to myślałem, że da się go porównać w ten sam sposób *czytaj ,,do zera". - Kenzy1 2014-08-15 14:39
do zera też możesz: if (pi==0) — po prostu odradzam pisania !pi jeśli chodzi o sprawdzenie NULL. - Azarien 2014-08-15 18:44

Pozostało 580 znaków

2014-08-15 14:00
0

Dobrze mam już rozwiązanie.

Otóż przy wywołaniu funkcji load z klasy QPixmap, Obiekt klasy QPainter tak jakby... ...rozłączył się z mapą.

 pi->begin(map);
 pi->drawLine(x,y,x1,y1);
 pi->end();

Wystarczyło dodać dwie linijki: begin i end.
Będę wdzięczny, jeśli ktoś mi wytłumaczy dokładnie, dlaczego tak się stało.

Dziękuję i pozdrawiam ;)

dodanie znacznika <code class="cpp"> - furious programming

edytowany 1x, ostatnio: furious programming, 2014-08-15 15:11
Wstawiaj kod w odpowiednie dla danego języka znaczniki kolorujące składnię; - furious programming 2014-08-15 15:11

Pozostało 580 znaków

2014-08-15 14:02
kq

QFileDialog::getSaveFileName i QFileDialog::getOpenFileName to funkcje statyczne, nie potrzebujesz tworzyć do nich nowego obiektu.

Powinieneś sprawdzać wynik ich działania, po wciśnięciu anuluj zwracany jest pusty string (""), który potem bezmyślnie przekazujesz dalej.

Przy okazji, popracuj nad wyciekami pamięci, wszystko zaalokowane za pomocą new bez podania rodzica w konstruktorze (lub ustawienia go później, ale tego nie robisz) to wyciek, np. Twój QPen * pi.


Pokaż pozostałe 4 komentarze
Rozumiem, że miałoby to wyglądać mniej więcej tak: zamiast pi->drawline[**] to this->pi->drawline[***] - Kenzy1 2014-08-15 14:24
Właśnie czytałem, że Qt ,,samo" dba o zwalnianie pamięci. W c należało pamiętać o delete i myśleć, co się kasuje *i że tylko raz można!. Tu ta automatyka: pojawia się, znika, cuduje, jest dla mnie troszkę niejasna. - Kenzy1 2014-08-15 14:26
Nie wszystkie klasy Qt dziedziczą po QObject, QPainter jest jedną z tych co nie dziedziczą, więc nie możesz ustawić u rodzica, tylko sam musisz zająć się zwolnieniem pamięci w odpowiednim miejscu (np. w destruktorze, albo jeszcze lepiej zmień typ pi z QPainter* na std::unique_ptr&lt;QPainter&gt;. unique_ptr: http://en.cppreference.com/w/cpp/memory/unique_ptr - kq 2014-08-15 14:27
,,Mądrzejszy wskaźnik". Dzięki wielkie ;). - Kenzy1 2014-08-15 14:31
dodanie this-&gt; przed odwołaniem do pola klasy nic nie robi i nic nie daje. koledze @kq chodziło o podanie this jako parametru konstruktora klasy dziedziczącej po QObject. tylko wtedy Qt „samo” zadba o zwolnienie pamięci. - Azarien 2014-08-15 14:34

Pozostało 580 znaków

2014-08-15 14:06
1

Uruchom w trybie debug (zielona strzałka z robalem) jak błąd wystąpi to program się zatrzyma i dostaniesz więcej informacji co jest źle.
Ja zgaduje, że próbujesz rysować poza granicami obrazka.
Najlepiej załącz zip-a z całym kodem by łatwo było go sprawdzić.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.

Pozostało 580 znaków

2014-08-15 14:18
0

Pliki w .tar

http://hostuje.net/file.php?id=eaf6c2e8abb33bd6d5c7807b80c4fb7d

Pozostało 580 znaków

2014-08-16 11:36
0

Cały problem polega na tym, że przekomponowujesz z zarządzaniem pamięcią i nadużywasz pól klasy.
Pozostawiając błędny design aplikacji, to powinno być zrobione tak jak w załączniku.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.

Pozostało 580 znaków

Liczba odpowiedzi na stronę

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