Название: [3.1.1]QCanvasLine Отправлено: 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 Название: QCanvasLine Отправлено: Dendy от Март 20, 2006, 11:33 А если свернуть/развернуть окно линии появляются?
Название: QCanvasLine Отправлено: faust от Март 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. Если так, то эти классы доработаны или просто взяты из предыдущей третьей версии и переименованы? Название: QCanvasLine Отправлено: Hordi от Март 22, 2006, 10:33 Исходник запость. Ничего сложного там нет, может где-то просто ошибся.
Название: QCanvasLine Отправлено: faust от Март 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); } а этот вызывает предыдущий метод и отображает линию на канве ============================================= зы. Тупо, что мои табы и пробелы в начале строки грубо поскипались веб-интерфейсом добавлено спустя: кстати, весь прожект можно посмотреть тут: ftp://public.ntu-kpi.kiev.ua/incoming/lines/lines.tar.bz2 если ссылка будет нерабочей - пишите, я выложу снова + скину в мыло, кому интересно, т.к. этот сервер ненадежен зы. Для рисования выбрать кнопку Lines. Для удаления последней нарисованной линии: menu Edit->Undo last->line, для удаления всех линий: menu Edit->Clear all |