ну держитесь (:
я унаследовал класс 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