Russian Qt Forum
Сентябрь 28, 2024, 06:22 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [3.1.1]QCanvasLine  (Прочитано 4548 раз)
faust
Гость
« : Март 18, 2006, 10:01 »

с сабжем наблюдается такая трабла - линия не всегда показывается на канве после своего создания. По событию contentsMousePressEvent на экране появлется линия, смещенная относительно предыдущей на 20 пикселей:

QCanvasLine *p_trash;
(p_trash = new QCanvasLine(p_canv))->setPoints(xx1,yy1,xx2,yy2);
p_trash->show();
p_canv->update();
xx1 += 20;
xx2 += 20;

где p_canv - указатель на канву, xx1,yy1,... - глобальные переменные, инициализированные выше. Каждая последующая линия при клике рисуется на 20 точек правее предыдущей. Кликаю несколько десятков раз...

а теперь самое интересное - случайным образом некоторые линии тупо не отрисовываются, при чем все эти неотрисовываемые линии попадают, как правило в первую десятку-пятнадцатку. Т.е., на экране в некоторых местах между соседними видимыми линиями расстояние не 20, а 40 (иногда 60 - если дважды подряд линии не покажутся)

нижеследующие методы (даже Brush туда вписал) не помогли:
p_trash->setPen(Qt::black);
p_trash->setBrush(Qt::green);
p_trash->setVisible(true);

вот что говорится для последнего метода в мануале:
void QCanvasItem::setVisible ( bool yes ) [virtual]
Makes the canvas item visible if yes is TRUE, or invisible if yes is
FALSE. The change takes effect when QCanvas::update() is next called.

в общем, лажа какая-то рэндомной природы. Все линии есть, но не всех их видно

зы. Здесь проблемы возникали где-то с каждой пятой линией из первых пятнадцати, дальше можно было хоть сотню линий накликать - все они красиво отрисовывались. Но когда я перед этим создавал линии как поле структуры, являющейся звеном списка (без юзанья STL), и указатель на этот список хранил в классе - тогда линии не отображались совершенно случайным образом - где-то каждая седьмая, и происходило это не только в первой десятке

ззы. Qt 3.1.1
Записан
Dendy
Гость
« Ответ #1 : Март 20, 2006, 11:33 »

А если свернуть/развернуть окно линии появляются?
Записан
faust
Гость
« Ответ #2 : Март 22, 2006, 02:02 »

Цитировать
А если свернуть/развернуть окно линии появляются?


нет, не появляются. И никакие апдейты канвы не помогают. Правда, я так и не понял, как воспользоваться методом update() у QCanvasItem в секции protected (иерархия: QCanvasItem <-- QCanvasPolygonalItem <-- QCanvasLine)

вырезка их мануала:
void QCanvasItem::update () [protected]
Call this function to repaint the canvas's changed chunks.

кстати, вопрос - как в четвертой Qt реализована графика? Я так понял, через классы с именами, начинающимися с Q3. Если так, то эти классы доработаны или просто взяты из предыдущей третьей версии и переименованы?
Записан
Hordi
Гость
« Ответ #3 : Март 22, 2006, 10:33 »

Исходник запость. Ничего сложного там нет, может где-то просто ошибся.
Записан
faust
Гость
« Ответ #4 : Март 23, 2006, 05:30 »

ну держитесь (:


я унаследовал класс CcanvasView от QCanvasView, чтобы прописать в нем события. По событию mousePress:

NSline::Clines *pc_lines;
extern QCanvas *p_canv;

void CcanvasView::contentsMousePressEvent(QMouseEvent* e){
   pc_lines->getLineCurr()->was_moving = false;
   pc_lines->getLineCurr()->lineTmp = new QCanvasLine(p_canv);
   pc_lines->getLineCurr()->lineTmp->setPoints(e->x(),e->y(),e->x(),e->y());
}
тут в структуру типа "текущая отрисовываемая линия" заносится was_moving=false (т.е., еще перемещения мыши с зажатой кнопкой не было); записываю в нее же указатель на линию и устанавливаю начальные точки (в данном случае пока что линия вырождена в точку)

дальше обрабатываем событие mouseMove:

void CcanvasView::contentsMouseMoveEvent(QMouseEvent *e){
   pc_lines->getLineCurr()->was_moving = true;
   NSline::drawLineOther(pc_lines->getLineCurr()->lineTmp,e->x(),e->y());
   p_canv->update();
}
здесь записываем все в ту же структуру, хранящей инфу о текущей соаздаваемой линии, что курсор перемещался (was_moving=true) - это нужно будет для события mouseRelease; вызываю метод для отрисовки линии (параметры - указатель на линию, новые координаты конца линии); апдейтим канву

void CcanvasView::contentsMouseReleaseEvent(QMouseEvent *e){
   if (pc_lines->getLineCurr()->was_moving)
      pc_lines->drawNewLine(pc_lines->getLineCurr()->lineTmp);
   else
      delete pc_lines->getLineCurr()->lineTmp;
   pc_lines->getLineCurr()->lineTmp = 0;
   p_canv->update();
}
здесь проверяем, наступало ли событие mouseMove после mousePress (флаг was_moving). Если да - добавить линию в список линий, хранящийся в классе, взяв ее из структуры "текущая отрисовываемая линия". Иначе - удалить ее. Затем из структуры текущей линии удаляем указатель на линию (т.к. эта линия теперь доступна из списка линий класса, либо она удалена). Апдейтим канву





хедерь graphitems.h:
=============================================
namespace NSline
{
      //struct for all lines
      struct SlistLines{//звено списка линий
            QCanvasLine *line;//указатель на линию
            int lineId;//идентификатор
            SlistLines *lineNext;//указатель на следующее звено
      };

      //struct for currently drawing line
      struct SdrawingLine{//рисуемая сейчас линия
            bool was_moving;   //for mouseMoveEvent
            QCanvasLine *lineTmp;//указатель на линию
      };

      //struct for line's formula: Ax + By + C = 0
      struct SformulaLine{
            float A, B, C;
      };

      void drawLineOther(QCanvasLine *InPCanvLine, int InEndx, int InEndy);
      SformulaLine *formula(QCanvasLine *inp_canvline);

      //class for lines manage
      class Clines{
      public:
            Clines();
            ~Clines();
            int addNewLine(QCanvasLine *InLine);//only add new line, no show
            int drawNewLine(QCanvasLine *InLine);//add and show new line
            SdrawingLine *getLineCurr() const {return lineCurr;}
      private:
            SlistLines *linesAll;//список линий (список структур)
            SdrawingLine *lineCurr;//рисуемая сейчас линия
            int lastUsedId;
      };
}
=============================================




кусок сырца graphitems.cpp для этого неймспеса:
=============================================
extern QCanvas *p_canv;

//===namespace lines==================================================
void NSline::drawLineOther(QCanvasLine* inp_canvline, int inEndx, int inEndy){
      inp_canvline->setPoints(inp_canvline->startPoint().x(),inp_canvline->startPoint().y(),inEndx,inEndy);
      inp_canvline->show();
}
этот метод просто меняет координаты конца линии, вызывает метод show() для нее

//---class lines------------------------------------------------------
NSline::Clines::Clines(){
      linesAll = 0;
      lineCurr = 0;
      lastUsedId = 0;
      lineCurr = new SdrawingLine;
      lineCurr->was_moving = false;
      colorSelect = Qt::red;
}

NSline::Clines::~Clines(){
      delLinesAll();
}

int NSline::Clines::addNewLine(QCanvasLine *InLine){//only add new line, no show
      if (!linesAll){//если еще не создан список линий
            linesAll = new SlistLines();
            linesAll->line = InLine;
            linesAll->line->setPen(*(new QPen(Qt::black)));
            linesAll->line->show();
            linesAll->lineId = ++lastUsedId;
      }
      else{//если уже есть список
            SlistLines *p_line_tmp = linesAll;//запоминаем указатель на него
            while (p_line_tmp->lineNext)//идем до последней линии
                  p_line_tmp = p_line_tmp->lineNext;
            SlistLines *p_line_creating = new SlistLines();//создаем новое звено списка
            p_line_tmp->lineNext = p_line_creating;//добавляем его в список
            p_line_creating->line = InLine;
            p_line_creating->line->setPen(*(new QPen(Qt::black)));
//            p_line_creating->line->show();
            p_line_creating->lineId = ++lastUsedId;
            p_line_creating->lineNext = 0;
      }

      if (InLine->pen().color() != Qt::black)//просто проверка
            printf("[ warn ] line color not black\n");

      if (!InLine->visible())//тоже просто проверка
            printf("[ warn ] line not visible\n");

      return lastUsedId;
}
этот метод добавляет переданную ему линию в список не отображая на канве

int NSline::Clines::drawNewLine(QCanvasLine *InLine){//add and show new line
      InLine->show();
      p_canv->update();
      return addNewLine(InLine);
}
а этот вызывает предыдущий метод и отображает линию на канве

=============================================


зы. Тупо, что мои табы и пробелы в начале строки грубо поскипались веб-интерфейсом

добавлено спустя:

 кстати, весь прожект можно посмотреть тут:
http://ftp://public.ntu-kpi.kiev.ua/incoming/lines/lines.tar.bz2

если ссылка будет нерабочей - пишите, я выложу снова + скину в мыло, кому интересно, т.к. этот сервер ненадежен

зы. Для рисования выбрать кнопку Lines. Для удаления последней нарисованной линии: menu Edit->Undo last->line, для удаления всех линий: menu Edit->Clear all
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.047 секунд. Запросов: 21.