פורסם: 05/08/2003 - 12:31
נושא ההודעה:
|
שלום,
בזמן שאני בונה תוכנה כלשהיא אני נאלץ ליצור WIDGET משלי שמבוסס על QFrame
אני מנסה להשתמש בQPainter ולפי מה שהבנתי אני מפעיל אותו על כל מה שמבוסס QWidget.
אבל הוא לא מצייר לי,
יש לי WIDGET של גודל 120 על 120,
יש למישהו דוגמה שאני אוכל למוד ממנה?
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 12:46
נושא ההודעה:
|
העפת מבט במדור הדוגמאות בQt Assistant או באתר של TrollTech? אגב, הTutorial הראשון שם עוסק בציור.
_________________ Ich möchte ein Klicken hören
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 12:51
נושא ההודעה:
|
ציטוט: |
ב 2003-08-05 09:46, IgKh כתב:
העפת מבט במדור הדוגמאות בQt Assistant או באתר של TrollTech? אגב, הTutorial הראשון שם עוסק בציור.
|
העפתי מבט,
ואגב הTUTORIAL הראשון עוסק בציור אבל לא מסבירים כמו בשום מקום באתר איך מציגים אותו
[ נערך על-ידי אייל בתאריך 05/08/03 09:51:49 ]
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 13:10
נושא ההודעה:
|
אפשר לראות את הקוד?
_________________ Ich möchte ein Klicken hören
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 13:23
נושא ההודעה:
|
#include
#include
#include
#include
#include
#include
class JoyMapView : public QFrame
{
public:
JoyMapView( QFrame *parent=0, const char *name=0 );
void setDot(int Place);
};
JoyMapView::JoyMapView( QFrame *parent, const char *name )
: QFrame( parent, name )
{
setMinimumSize( 140, 140 );
setMaximumSize( 140, 140 );
setBackgroundMode(Qt::FixedColor);
setPaletteBackgroundColor(QColor(255,255,255));
QPainter p( this );
p.setBrush( blue );
p.setPen( NoPen );
p.translate( 0, rect().bottom() );
p.drawPie( QRect(-35, -35, 70, 70), 0, 90*16 );
p.rotate( -20 );
p.drawRect( QRect(33, -4, 15, );
}
int main( int argc, char **argv )
{
QApplication JoyTest( argc, argv );
JoyMapView JoyView(0);
JoyView.show();
JoyTest.setMainWidget(&JoyView);
return JoyTest.exec();
}
[ נערך על-ידי אייל בתאריך 05/08/03 10:25:09 ]
[ נערך על-ידי אייל בתאריך 05/08/03 10:25:33 ]
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 13:24
נושא ההודעה:
|
אהה!!
ווטסאפ עיוות הכל,
ומאיפה הגיע הסמיליי הזה!?
אני לא תכנתתי סמיילי
אני חושב שעכשיו זה בסדר רשום
[ נערך על-ידי אייל בתאריך 05/08/03 10:26:26 ]
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:13
נושא ההודעה:
|
אייל, היות ואני לא ממש מנוסה ב-Qt, זה רק ניחוש, אבל:
קודם כל, אין הגיון בציור בתוך הבנאי. פונקצית הבנאי נועדה לאתחול עצמים מהמחלקה. כמו-כן, המחלקה שלך יורשת ממחלקת QFrame, אשר מכילה את השיטה הוירטואלית המוגנת:
קוד: | virtual void drawContents ( QPainter * ) |
להערכתי, עליך לדרוס את הפונקציה הזו במחלקה שלך. המצביע לאובייקט QPainter יועבר לפונקציה זו (אני מנחש שבאופן אוטומטי, כמו שקורה למחלקות אחרות היורשות מ-QFrame). עצם העובדה שהמחלקה שלך יורשת מ-QFrame, הופכת את ההעברה הזו לאפשרית (פולימורפיזם).
אם כן, כפי שאמרתי זה רק ניחוש, אבל להערכתי הוא הגיוני ומומלץ שתנסה זאת. שים את הקוד הדואג לצייר את ה-widget שלך בפונקציה drawContents, ובבנאי שים רק אתחולים של המחלקה שלך.
אני מאמין שזה יעבוד .
[addsig]
_________________
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:30
נושא ההודעה:
|
הציור הממשי צריך להתבצע בפונקציה paintEvent. היא מקבלת פרמטר חובה מסוג QPaintEvent *. אם אני לא טועה QT תקרא לפונקתיה לבד כשיגיע הזמן לצייר את הרכיב ולכן אתה לא צריך לקרוא לפונקציה לבד.
אבל כנראה הדרך של wilad טובה יותר.
[ נערך על-ידי IgKh בתאריך 05/08/03 11:32:19 ]
_________________ Ich möchte ein Klicken hören
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:30
נושא ההודעה:
|
ציטוט: |
ב 2003-08-05 11:13, wliad כתב:
אייל, היות ואני לא ממש מנוסה ב-Qt, זה רק ניחוש, אבל:
קודם כל, אין הגיון בציור בתוך הבנאי. פונקצית הבנאי נועדה לאתחול עצמים מהמחלקה. כמו-כן, המחלקה שלך יורשת ממחלקת QFrame, אשר מכילה את השיטה הוירטואלית המוגנת:
קוד: | virtual void drawContents ( QPainter * ) |
להערכתי, עליך לדרוס את הפונקציה הזו במחלקה שלך. המצביע לאובייקט QPainter יועבר לפונקציה זו (אני מנחש שבאופן אוטומטי, כמו שקורה למחלקות אחרות היורשות מ-QFrame). עצם העובדה שהמחלקה שלך יורשת מ-QFrame, הופכת את ההעברה הזו לאפשרית (פולימורפיזם).
אם כן, כפי שאמרתי זה רק ניחוש, אבל להערכתי הוא הגיוני ומומלץ שתנסה זאת. שים את הקוד הדואג לצייר את ה-widget שלך בפונקציה drawContents, ובבנאי שים רק אתחולים של המחלקה שלך.
אני מאמין שזה יעבוד .
|
אני אבדוק,
צודק טעות שלי
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:33
נושא ההודעה:
|
ציטוט: |
ב 2003-08-05 11:30, IgKh כתב:
wilad, כמעט.
הציור הממשי צריך להתבצע בפונקציה paintEvent. היא מקבלת פרמטר חובה מסוג QPaintEvent. אם אני לא טועה QT תקרא לפונקתיה לבד כשיגיע הזמן לצייר את הרכיב ולכן אתה לא צריך לקרוא לפונקציה לבד
|
כלומר חוצמהשגיאה עם הבנאי,
איזה עוד שגיאה יש לי?
כי גם שזה מחוץ לבנאי זה לא עובד...
אז לעשות פונקציה painEvent?
לאן אתם חותרים?
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:35
נושא ההודעה:
|
אני לא גאון בC++ ולא מזמן אני רק התחלתי ללמוד את זה..
אני הבנתי אתכם אבל האם תוכלו לרשום לי את הקוד,
כלומר איך אני יוצר את drawContent הבנתי, אבל אני יודע שיש דרך להעביר את הנתונים עוד בשורת ההצבה,
ואני לא בדיוק מתמצא בזה,
האם תוכלו לעזור לי?
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:35
נושא ההודעה:
|
ציטוט: |
ב 2003-08-05 11:13, wliad כתב:
אייל, היות ואני לא ממש מנוסה ב-Qt, זה רק ניחוש, אבל:
קודם כל, אין הגיון בציור בתוך הבנאי. פונקצית הבנאי נועדה לאתחול עצמים מהמחלקה. כמו-כן, המחלקה שלך יורשת ממחלקת QFrame, אשר מכילה את השיטה הוירטואלית המוגנת:
קוד: | virtual void drawContents ( QPainter * ) |
להערכתי, עליך לדרוס את הפונקציה הזו במחלקה שלך. המצביע לאובייקט QPainter יועבר לפונקציה זו (אני מנחש שבאופן אוטומטי, כמו שקורה למחלקות אחרות היורשות מ-QFrame). עצם העובדה שהמחלקה שלך יורשת מ-QFrame, הופכת את ההעברה הזו לאפשרית (פולימורפיזם).
אם כן, כפי שאמרתי זה רק ניחוש, אבל להערכתי הוא הגיוני ומומלץ שתנסה זאת. שים את הקוד הדואג לצייר את ה-widget שלך בפונקציה drawContents, ובבנאי שים רק אתחולים של המחלקה שלך.
אני מאמין שזה יעבוד .
|
זה קצת מוזר כי הוא לא היה מצליח לקמפל אם הוא לא היה מחליף את Virtual Method בפונקציה בשם וחתימה זהים במופע שלו מחלקה היורשת מאותה מחלקה בסיסית QFrame.
_________________ Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that cant stand one bit of competition.
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:40
נושא ההודעה:
|
האם כך צריכה להתבצע ההגדרה?
class JoyMapView : public QFrame
{
public:
JoyMapView( QFrame *parent=0, const char *name=0 );
void setDot(int Place);
void drawContents(QPainter *);
};
JoyMapView::drawContents(QPainter *)
: QFrame::drawContents(QPainter *)
{
/////כאן תבוא הציור
}
[ נערך על-ידי אייל בתאריך 05/08/03 11:43:20 ]
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:48
נושא ההודעה:
|
ככה:
קוד: | class JoyMapView : public QFrame
{
public:
JoyMapView(QFrame * parent = 0, const char * name = 0);
void drawContents(QPainter *);
};
JoyMapView::JoyMapView(QFrame * parent, const char * name): QFrame(parent, name)
{
}
void JoyMapView::drawContent(QPainter * painter)
{
//painting
}
|
שים לב שהQPainter שאתה מקבל הוא פתוח ו אסור לסגור אותו.
[ נערך על-ידי IgKh בתאריך 05/08/03 11:53:18 ]
_________________ Ich möchte ein Klicken hören
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:53
נושא ההודעה:
|
ציטוט: |
ב 2003-08-05 11:35, dittigas כתב:
זה קצת מוזר כי הוא לא היה מצליח לקמפל אם הוא לא היה מחליף את Virtual Method בפונקציה בשם וחתימה זהים במופע שלו מחלקה היורשת מאותה מחלקה בסיסית QFrame.
|
לא מוזר כלל. הפונקציה drawContents מוגדרת כפונקציה וירטואלית, לא כוירטואלית טהורה. המחלקה QFrame אינה מחלקה אבסטרקטית, היא מכילה מימוש מינימאלי של הפונקציה drawContents.
מחלקה היורשת מ-QFrame ורוצה לצייר נתונים ספציפיים שלה, צריכה לדרוס את המימוש שמציעה QFrame, לא לממש את הממשק שהיא מציעה (היא לא מציעה ממשק).
כאן הפולימורפיזם בא בעוצמתו המלאה, מצביע ל-QFrame המכוון על עצם מסוג של מחלקה יורשת, יביא לשימוש במימוש המתאים של המחלקה היורשת ולא בזה של QFrame.
אני לא מכיר את שיטת האירועים שהוצעה כאן, אבל כמו שאמרתי אין לי נסיון ב-Qt. אני מציע שתנסה את מה שהצעתי, ותגיד אם זה הצליח לך. אם לא אולי שיטת האירועים היא הדרך הנכונה. בכל מקרה, אשמח אם תכתוב סיכום לאשכול כשתמצא את הפתרון.
בנוגע לקוד ששאלת לגביו אם לזו הכוונה: כן באופן עקרוני זאת הכוונה, רק מומלץ שתזיז את הפונקציה drawContents לחלק המוגן (protected) ולא לחלק הציבורי (public), היות והיא אינה אמורה להקרא על-ידי קוד חיצוני.
[addsig]
_________________
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 14:59
נושא ההודעה:
|
תודה,
אבל יש לי שגיאה:
jscal.cpp:28: ISO C++ forbids declaration of `drawContents' with no type
jscal.cpp:28: prototype for `int JoyMapView::drawContents(QPainter*)' does not
match any in class `JoyMapView'
jscal.cpp:12: candidate is: virtual void JoyMapView::drawContents(QPainter*)
jscal.cpp:28: `int JoyMapView::drawContents(QPainter*)' and `virtual void
JoyMapView::drawContents(QPainter*)' cannot be overloaded
jscal.cpp: In member function `int JoyMapView::drawContents(QPainter*)':
jscal.cpp:28: warning: unused parameter `QPainter*painter'
השורה 12 היא שורת ההצהרה:
void drawContents(QPainter *);
והשורה 28 היא:
JoyMapView::drawContents(QPainter * painter){
אגב בשורה הזאת (2 אז אני משתמש בpainter כדי לצייר?
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:05
נושא ההודעה:
|
האם העברת את הפונקציה ל-protected?
עוד דבר ששמתי לב אליו בקוד שלך, במימוש הפונקציה מחוץ להגדרת המחלקה היא מוגדרת כ-int או יותר נכון לא מוגדרת כמחזירה ערך בכלל (מה שאוטומטית הופך אותה ל-int):
קוד: | JoyMapView::drawContents(QPainter *)
: QFrame::drawContents(QPainter *)
{
/////כאן תבוא הציור
} |
בעוד שהפונקציה מוגדרת כ-void. שנה את המימוש לצורה הבאה:
קוד: | void JoyMapView::drawContents(QPainter *p)
{
/////כאן תבוא הציור
// For example: p->drawMethod();
} |
מקווה שעכשיו זה יעבוד לך .
_________________
חתימה? אוקיי אבל שתהיה דיגיטלית LOL
[ נערך על-ידי wliad בתאריך 05/08/03 12:09:27 ]
[ נערך על-ידי wliad בתאריך 05/08/03 12:11:29 ]
_________________
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:13
נושא ההודעה:
|
העברתי לPORTECTED ולקחתי לצומת ליבי את כל ההערות אבל זהעדיין אל עובד.
הנה הקוד הנוכחי:
class JoyMapView : public QFrame
{
protected:
12: drawContents(QPainter *);
public:
14: int JoyMapView(QFrame * parent = 0, const char * name = 0);
};
19: int JoyMapView::JoyMapView( QFrame *parent, const char *name ) : QFrame( parent, name )
{
setMinimumSize( 140, 140 );
setMaximumSize( 140, 140 );
setBackgroundMode(Qt::FixedColor);
25: setPaletteBackgroundColor(QColor(255,255,255));
return 0;
}
והנה השגיאה:
jscal.cpp:12: ISO C++ forbids declaration of `drawContents' with no type
jscal.cpp:14: return type specification for constructor invalid
jscal.cpp:12: conflicting return type specified for `virtual int
JoyMapView::drawContents(QPainter*)'
/usr/qt/3/include/qframe.h:116: overriding `virtual void
QFrame::drawContents(QPainter*)'
jscal.cpp:19: return type specification for constructor invalid
jscal.cpp: In constructor `JoyMapView::JoyMapView(QFrame*, const char*)':
jscal.cpp:25: returning a value from a constructor
make: *** [jscal.o] Error 1
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:27
נושא ההודעה:
|
אתה סימנת את הבנאי כמחזיר ערך - דבר שאסור
ושחחת לסמן את פונקצית הציור כמחזירה void
_________________ Ich möchte ein Klicken hören
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:27
נושא ההודעה:
|
לא משנה הצלחתי לסדר,נ
זה VOID ולא INT,
נקווה שהפעם אני אצליח לצייר
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:29
נושא ההודעה:
|
אוקיי, היות ואני רואה שלא הבנת למה התכוונתי, להלן דוגמא:
קוד: |
class MyFrame: public QFrame
{
// Private member variables and methods:
protected:
// Protected member variables and methods:
virtual void drawContents(QPainter *);
public:
// Public member variables and methods:
MyFrame(...):QFrame(...)
{
...
}
};
void MyFrame::drawContents(QPainter *p)
{
// Here goes the drawing:
// For example: p->drawMethod();
}
|
מקווה שזה יבהיר את העניין.
[addsig]
_________________
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:33
נושא ההודעה:
|
WLIAD אמנם אני עדיין לא מבין מה אתה מנסה להסביר לי,
אבל זה עובד וזה מצייר!!
אגב למי שמתעניין אני בונה כלי גרפי לכיול ובדיקה של ג'ויסטיק
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:37
נושא ההודעה:
|
אם זה עובד, למה שלא תכתוב סיכום של מה שעשית?
[addsig]
_________________
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:48
נושא ההודעה:
|
אז ככה, ואני לא מחושב שכרגע הINCLUDES שעשיתי משנים.
אני יצרתי WIDGET משלי שמבוסס על QFRAME
class JoyMapView : public QFrame
ואז הצהרתי פונקציה בונה שתפקידה לכוון את הגודל של הפקד (העדפתי לשים את הכיוון גדלים כפונקציה בונה כיוון שאחר כך אני אהפוך את זה לדינאמי, כלומר שהגודל נקבע ביצירת הWIDGET ולכן אני אצטרך לאפס אותם בפונקציה הבונה אחר כך).
public:
JoyMapView(QFrame * parent = 0, const char * name = 0);
אחר כך ישנה את הפוקנציה drawContents שהיא פונקציה וירטואלית שניתנת לשינוי ונקראת בכל פעם של יצירת הפקד, זוהי ההתנהגות של QFrame ולכן רשמתי:
protected:
void drawContents(QPainter *);
והחלק העיקרי והבעייתי שהיה הוא האפשרות לצייר, ולכן הקוד שהכנסתי לdrawContents היה הקוד ציור:
void JoyMapView::drawContents(QPainter *p)
{
p->setBrush( blue );
p->setPen( NoPen );
p->end();
}
כמובן זה דורש פונקציות של ציור אבל זה יעבוד...
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:55
נושא ההודעה:
|
שתי הערות (המלצות) לסיכום הדיון:
1. את פונקצית הבנאי מומלץ לממש כ-inline. מימוש שלה בתוך הגדרת המחלקה יעשה את העבודה. אם אתה מתעקש לממש אותה מחוץ להגדרה, מומלץ להגדיר אותה כ-inline מפורשות על-ידי שימוש במילה השמורה inline לפני כותרת הפונקציה.
2. את הפונקציה drawContents מומלץ להמשיך להגדיר כוירטואלית מתוך מחשבה לעתיד. אם בעתיד תרצה להוריש מחלקה נוספת מהפקד שאתה יצרת, תאבד את הפולמורפיות של עץ ההורשה עבור פונקציה זו, אם במחלקת הבסיס היא לא תהא מוגדרת כוירטואלית.
בזאת לדעתי אפשר לסגור את הדיון, המשך עבודה מוצלחת. נשמח לראות תצלום מסך של הפקד שלך בפעולה, ברגע שכזה יהיה אפשרי.
[addsig]
_________________
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 15:57
נושא ההודעה:
|
תצלום מסך בקרוב, הפקד כבר מתחיל להראות סימני חיים,
וכיוון שהמערכת חצי קיימת אני חושב שעד היום בערב אני אוכל לצרף תמונה ואפילו קוד מקור
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 16:06
נושא ההודעה:
|
אני יודע שאמרתי שאפשר לסגור את הדיון, אבל הערה אחת קטנה אני חייב.
הוצע כאן להכניס את קוד הציור לפונקציה בשם paintEvent. כמו שאמרתי כבר קודם, אין לי נסיון ב-Qt, אבל אני מכיר מעט את הטרמינולוגיה הנפוצה בתכנות בסביבת ממשק חלונאי.
Event מציין אירוע מערכת בד"כ. אני מניח אם כך (ותקנו אותי אם אני טועה) ש-paintEvent היא פונקציה הנקראת באופן אוטומטי בכל פעם שיש לבצע ציור של הפקד. כמו-כן, אני מאמין שפונקציה זו לא נדרשת לדריסה היות והיא קוראת (סביר להניח) לפונקציה drawContents לצורך הציור האמיתי. היות והפקד החדש יורש מפקד קיים, הפונקציה האמיתית המבוצעת (בגלל פולימורפיזם) היא זושל המחלקה היורשת.
אם כן, לדעתי paintEvent הינה פונקציה המטפלת באירוע הציור ובד"כ לא יהיה צורך לדרוס אותה. הציור עצמו לא מבוצע בה כלל (ולראיה, היא לא מקבלת מצביע ל-QPainter כפרמטר).
[addsig]
_________________
|
|
חזרה לתוכן הדיון |
פורסם: 05/08/2003 - 17:54
נושא ההודעה:
|
paintEvent אכן נקראת כאשר מתקבלת הודעת מערכת שהפקד שונה\הוזז\הוסתר\נגלה אך היא ברמה יותר נמוכה מdrawContent. בעוד שdrawContent ממושת בQFrame והיא לא יותר מפונקצית נוחות למטרות המסוימות שQFrame מוגדר אליהם(QPainter מוגדר מראש וכו), מקורה של paintEvent היא בQWidget - מחלקה מופשטת שאין לה יעוד מסוים פרט להיותה הבסיס המשותף של כל הפקדים. לפיכך paintEvent היא הרבה יותר גמישה - אתה יוצר את הQPainter שלך לבד, אתה מקבל מידע על הריבוע הספציפי ששונה, אתה יותר גמיש באיפה אתה מצייר).
_________________ Ich möchte ein Klicken hören
|
|
חזרה לתוכן הדיון |
פורסם: 06/08/2003 - 00:00
נושא ההודעה:
|
אני לא יכול שלא לתקן...
צריך להשתמש בpaintEvent.
היא נקראת בעת יצירת הציור וגם בעת יצירה מחדש.
כלומר,
כאשר יוצרים ציור יוצרים EVENT על הפקד שישצייר,
והפקד שמכיר בפקודה repaint מריץ שוב את הפקודה paintEvent ובכך עם מגדירים משתנה לאנימציה ועושים repaint אז ככה ניתן לעשות אנימציה.
ככה גם רשום במדריך וגם בעזרה של QT.
אחר כך אני ארשום קוד נכון,
פשו אני ממשיך לבנו את זה,
שברתי כל היום את הראש איך אני עושה אנימציה, ועכשיו אני יכול לעשות את ה"אנימציה" של התזוזה
|
|
חזרה לתוכן הדיון |
פורסם: 21/08/2003 - 23:00
נושא ההודעה:
|
אייל,
מאחר ותיקנת שוב, והבטחת גם תמונה וגם קוד מתוקן, אני עדיין מחכה. אשמח אם תדביק פה תמונה של הפקד שבנית וגם את קוד המקור שלו, ואת הפתרון הטוב ביותר שמצאת לשאלה המקורית.
[addsig]
_________________
|
|
חזרה לתוכן הדיון |
|