PDA

View Full Version : سوال در مورد qt



nasrin55
پنج شنبه 21 خرداد 1388, 09:26 صبح
این چه معنی می دهد؟ کارش چیست؟
setFocusProxy


The LCDRange sets the slider to be its focus proxy. That means that when someone (the program or the user) wants to give the LCDRange keyboard focus, the slider should take care of it. QSlider (http://barnamenevis.org/forum/qslider.html) has a decent keyboard interface, so with just one line of code we've given LCDRange one.

همین طور مفهوم این جمله چیه؟


توی تکه کد زیر چه کاری را انجام می دهد؟


LCDRange::LCDRange(QWidget *parent)
: QWidget(parent)
{
QLCDNumber *lcd = new QLCDNumber(2);
lcd->setSegmentStyle(QLCDNumber::Filled);

slider = new QSlider(Qt::Horizontal);
slider->setRange(0, 99);
slider->setValue(0);

connect(slider, SIGNAL(valueChanged(int)),
lcd, SLOT(display(int)));
connect(slider, SIGNAL(valueChanged(int)),
this, SIGNAL(valueChanged(int)));

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(lcd);
layout->addWidget(slider);
setLayout(layout);

setFocusProxy(slider);
}

حامد مصافی
پنج شنبه 21 خرداد 1388, 09:54 صبح
تابع setFocusProxy به focusProxy مقدار می دهد. اگر یک widget فوکوس بگیرد می تواند آن را به یک widget دیگر پاس دهد، در واقع widget دوم نماینده دریافت فوکوس از سیستم عامل خواهد بود. در این مثال slider نماینده کلاس LCDRange خواهد بود. یعنی در موقع کلاس LCDRange فوکوس بگیرد آن را مستقیماً به slider انتقال خواهد داد و سایر widget ها (مانند lcd) توانایی دریافت فوکوس نخواهند داشت.

nasrin55
پنج شنبه 21 خرداد 1388, 10:07 صبح
یعنی چی که "تابع setFocusProxy به focusProxy مقدار می دهد"؟؟ این مقدار یعنی فوکوس یعنی چی ؟ ما که جایی از widget دومی که فوکوس میگیره استفاده نمی کنیم.
اگر که ما این خط آخر یعنی setfocousproxy(slider) را نمی نوشتیم چه اتفاقی می افتاد ؟؟

حامد مصافی
پنج شنبه 21 خرداد 1388, 10:19 صبح
کلاس شما دو widget در خود دارد با نام های lcd و slider. در حالت عادی کاربر می تواند روی هر یک از آنها کلیک کند و فوکوس به طور طبیعی به widget کلیک شده انتقال می یابد. اما در خط آخر دریافت فوکوس این کلاس به شی slider منتقل خواهد شد. یعنی چنانچه کاربر روی widget شما کلیک کند شی slider دارای فوکوس خواهد شد حتی اگر کاربر lcd را کلیک کرده باشد.

nasrin55
پنج شنبه 21 خرداد 1388, 10:51 صبح
یه سوال دیگه هم داشتم اینکه تو این تکه کد ما می توانیم مختصات حرکت یه گلوله را تعیین کنیم. برای حرکت دادن گلوله از movecenter استفاده میکنیم. این movecenter دقیقا چه کاری انجام میده؟؟ مقداری که به عنوان ورودی میگیره را چطوری ازش استفاده میکنه؟؟



QRect CannonField::shotRect() const
{
const double gravity = 4;

double time = timerCount / 20.0;
double velocity = shootForce;
double radians = shootAngle * 3.14159265 / 180;

double velx = velocity * cos(radians);
double vely = velocity * sin(radians);
double x0 = (barrelRect.right() + 5) * cos(radians);
double y0 = (barrelRect.right() + 5) * sin(radians);
double x = x0 + velx * time;
double y = y0 + vely * time - 0.5 * gravity * time * time;

QRect result(0, 0, 6, 6);
result.moveCenter(QPoint(qRound(x), height() - 1 - qRound(y)));

return result;
}

سوال دیگه هم این که qround در Qpoint چه کاری انجام میده؟؟ اصلا برای چی از Qpoint استفاده میکنیم؟؟

حامد مصافی
پنج شنبه 21 خرداد 1388, 11:04 صبح
movecenter:
مختصات یک نقطه را می گیرد و QRect را طوری جابه جا می کند که مرکز QRect منطبق بر نقطه مزبور باشد.


سوال دیگه هم این که qround در Qpoint چه کاری انجام میده؟؟
qRound در QPoint نیست. این یک تابع استاتیک در QtGlobal است که به منظور حذف قسمت بعد از ممیز در اعداد کاربرد دارد.



اصلا برای چی از Qpoint استفاده میکنیم؟؟
چون پارامتر ورودی تابع movecenter از نوع QPoint است. به بیان دیگر یک QPoint به منظور ذخیره سازی مختصات یک نقطه (با خصوصیات x و y) کاربرد دارد.

nasrin55
پنج شنبه 21 خرداد 1388, 11:22 صبح
در تابع moveshot زیر ، این خط

region= region.unite(shotR)
چه معنی می دهد؟



void CannonField::moveShot()
{
QRegion region = shotRect();
++timerCount;

QRect shotR = shotRect();

if (shotR.x() > width() || shotR.y() > height()) {
autoShootTimer->stop();
} else {
region = region.unite(shotR);
}
update(region);
}

حامد مصافی
پنج شنبه 21 خرداد 1388, 11:32 صبح
اول اینکه QRegion به منظور مشخص کردن یک ناحیه در Qt استفاده می شود.
تابع unite دو ناحیه را با هم ادغام می کند و اجتماع آن دو را بر می گرداند. برای مثال در خط فوق الذکر توسط شما اجتماع shotR با region در region قرار می گیرد.

nasrin55
پنج شنبه 21 خرداد 1388, 12:17 عصر
با تشکر بسیار از شما که سوالات من را جواب دادید.

یه سوال دیگه داشتم اینکه در تابع زیر intersects برای چی به کار رفته؟؟ درسته که میخواسته وقتی گلوله به هدف برخورد می کنه emit سیگنال hit را ، ولی چرا از intersect استفاده کرده؟؟ آیا میخواد محل برخورد گلوله با هدف را مشخص کنه؟؟




void CannonField::moveShot()
{
QRegion region = shotRect();
++timerCount;

QRect shotR = shotRect();

if (shotR.intersects(targetRect())) {
autoShootTimer->stop();
emit hit();
} else if (shotR.x() > width() || shotR.y() > height()) {
autoShootTimer->stop();
emit missed();
} else {
region = region.unite(shotR);
}
update(region);
}

حامد مصافی
پنج شنبه 21 خرداد 1388, 12:46 عصر
تابع intersects مشخص می کند که یک QRect با دیگری تداخل دارد یا خیر.
در مثال شما در صورتی که targetRect() با shotR تداخل داشته باشد (حداقل یک نقطه مشترک داشته باشند دستورات if اجرا خواهند شد.

lvlina_r
پنج شنبه 21 خرداد 1388, 17:36 عصر
1>moc_player.obj : error LNK2019: unresolved external symbol "public: void __thiscall Player::hiting(int)" (?hiting@Player@@QAEXH@Z) referenced in function "public: virtual int __thiscall Player::qt_metacall(enum QMetaObject::Call,int,void * *)" (?qt_metacall@Player@@UAEHW4Call@QMetaObject@@HPAP AX@Z)
1>debug\t13.exe : fatal error LNK1120: 1 unresolved externals
این ارور لینکی یعنی چه، وقتی slot hitting را بر می دارم دیگه این error را نمی ده.......


#ifndef BAZIKON_H
#define BAZIKON_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QLCDNumber;
class LCDRange;
QT_END_NAMESPACE
class Player : public QWidget
{
Q_OBJECT
public :
Player( QWidget *parent = 0);
void init();
QLCDNumber *shotsLeft ;
QLCDNumber *hits;
LCDRange *angel;
LCDRange *forse;

public slots:
void hiting();

signals:
void hitGame();

};

#endif

حامد مصافی
پنج شنبه 21 خرداد 1388, 18:26 عصر
clean and rebuild project

lvlina_r
پنج شنبه 21 خرداد 1388, 18:36 عصر
بازم ERROR می ده......:عصبانی++:

حامد مصافی
پنج شنبه 21 خرداد 1388, 18:49 عصر
پس احتمالاً جایی که Player را تعریف کرده اید این slot را پیاده سازی نکرده اید.

lvlina_r
پنج شنبه 21 خرداد 1388, 18:57 عصر
اره، comment کرده بودم، ممنون....، داشتم روانی می شدما...

lvlina_r
پنج شنبه 21 خرداد 1388, 19:06 عصر
و یه سوال بازم فکر می کنم ساده و خنده دار
چرا این تابع

void CannonField::newTarget()
{
static bool firstTime = true;

if (firstTime)
{
firstTime = false;
QTime midnight(0, 0, 0);
qsrand(midnight.secsTo(QTime::currentTime()));
}
target = QPoint(200 + qrand() % 190, 10 + qrand() % 255);
update();
}

این error ها را میده، قبلا نمیداد....

1>.\cannonfield.cpp(72) : error C2079: 'midnight' uses undefined class 'QTime'
1>.\cannonfield.cpp(72) : error C2078: too many initializers
1>.\cannonfield.cpp(73) : error C2228: left of '.secsTo' must have class/struct/union
1> type is 'int'
1>.\cannonfield.cpp(73) : error C2027: use of undefined type 'QTime'
1> d:\qt\4.4.3\include\qtgui\../../src/gui/kernel/qwindowdefs.h(79) : see declaration of 'QTime'
1>.\cannonfield.cpp(73) : error C3861: 'currentTime': identifier not found

حامد مصافی
پنج شنبه 21 خرداد 1388, 19:12 عصر
#include <qdatetime.h>

lvlina_r
پنج شنبه 21 خرداد 1388, 19:17 عصر
#include <qdatetime.h>
این include شده، ولی error می ده

حامد مصافی
پنج شنبه 21 خرداد 1388, 19:28 عصر
این include شده، ولی error می ده
لا ممکن. کل کد فایل را درج کنید.

lvlina_r
پنج شنبه 21 خرداد 1388, 19:55 عصر
#include <QDateTime>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QPainter>
#include <QTimer>

#include <math.h>
#include <stdlib.h>

#include "cannonfield.h"

CannonField::CannonField(QWidget *parent)
: QWidget(parent)
{
currentAngle = 45;
currentForce = 0;
timerCount = 0;
autoShootTimer = new QTimer(this);
connect(autoShootTimer, SIGNAL(timeout()), this, SLOT(moveShot()));
shootAngle = 0;
shootForce = 0;
target = QPoint(0, 0);
gameEnded = false;
barrelPressed = false;
setPalette(QPalette(QColor(250, 250, 200)));
setAutoFillBackground(true);
newTarget();
}

void CannonField::setAngle(int angle)
{
if (angle < 5)
angle = 5;
if (angle > 70)
angle = 70;
if (currentAngle == angle)
return;
currentAngle = angle;
update(cannonRect());
emit angleChanged(currentAngle);
}

void CannonField::setForce(int force)
{
if (force < 0)
force = 0;
if (currentForce == force)
return;
currentForce = force;
emit forceChanged(currentForce);
}

void CannonField::shoot()
{
if (isShooting())
return;
timerCount = 0;
shootAngle = currentAngle;
shootForce = currentForce;
autoShootTimer->start(5);
emit canShoot(false);
}

void CannonField::newTarget()
{
static bool firstTime = true;

if (firstTime)
{
firstTime = false;
QTime midnight(0, 0, 0);
qsrand(midnight.secsTo(QTime::currentTime()));
}
target = QPoint(200 + qrand() % 190, 10 + qrand() % 255);
update();
}

void CannonField::setGameOver()
{
if (gameEnded)
return;
if (isShooting())
autoShootTimer->stop();
gameEnded = true;
update();
}

void CannonField::restartGame()
{
if (isShooting())
autoShootTimer->stop();
gameEnded = false;
update();
emit canShoot(true);
}

void CannonField::moveShot()
{
QRegion region = shotRect();
++timerCount;

QRect shotR = shotRect();

if (shotR.intersects(targetRect())) {
autoShootTimer->stop();
emit hit();
emit canShoot(true);
} else if (shotR.x() > width() || shotR.y() > height()
|| shotR.intersects(barrierRect())) {
autoShootTimer->stop();
emit missed();
emit canShoot(true);
} else {
region = region.unite(shotR);
}
update(region);
}

void CannonField::mousePressEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton)
return;
if (barrelHit(event->pos()))
barrelPressed = true;
}

void CannonField::mouseMoveEvent(QMouseEvent *event)
{
if (!barrelPressed)
return;
QPoint pos = event->pos();
if (pos.x() <= 0)
pos.setX(1);
if (pos.y() >= height())
pos.setY(height() - 1);
double rad = atan(((double)rect().bottom() - pos.y()) / pos.x());
setAngle(qRound(rad * 180 / 3.14159265));
}

void CannonField::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
barrelPressed = false;
}

void CannonField::paintEvent(QPaintEvent * /* event */)
{
QPainter painter(this);

if (gameEnded) {
painter.setPen(Qt::black);
painter.setFont(QFont("Courier", 48, QFont::Bold));
painter.drawText(rect(), Qt::AlignCenter, tr("Game Over"));
}
paintCannon(painter);
paintBarrier(painter);
if (isShooting())
paintShot(painter);
if (!gameEnded)
paintTarget(painter);
}

void CannonField::paintShot(QPainter &painter)
{
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::black);
painter.drawRect(shotRect());
}

void CannonField::paintTarget(QPainter &painter)
{
painter.setPen(Qt::black);
painter.setBrush(Qt::red);
painter.drawRect(targetRect());
}

void CannonField::paintBarrier(QPainter &painter)
{
painter.setPen(Qt::black);
painter.setBrush(Qt::yellow);
painter.drawRect(barrierRect());
}

const QRect barrelRect(30, -5, 20, 10);

void CannonField::paintCannon(QPainter &painter)
{
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::blue);

painter.save();
painter.translate(0, height());
painter.drawPie(QRect(-35, -35, 70, 70), 0, 90 * 16);
painter.rotate(-currentAngle);
painter.drawRect(barrelRect);
painter.restore();
}

QRect CannonField::cannonRect() const
{
QRect result(0, 0, 50, 50);
result.moveBottomLeft(rect().bottomLeft());
return result;
}

QRect CannonField::shotRect() const
{
const double gravity = 4;

double time = timerCount / 20.0;
double velocity = shootForce;
double radians = shootAngle * 3.14159265 / 180;

double velx = velocity * cos(radians);
double vely = velocity * sin(radians);
double x0 = (barrelRect.right() + 5) * cos(radians);
double y0 = (barrelRect.right() + 5) * sin(radians);
double x = x0 + velx * time;
double y = y0 + vely * time - 0.5 * gravity * time * time;

QRect result(0, 0, 6, 6);
result.moveCenter(QPoint(qRound(x), height() - 1 - qRound(y)));
return result;
}

QRect CannonField::targetRect() const
{
QRect result(0, 0, 20, 10);
result.moveCenter(QPoint(target.x(), height() - 1 - target.y()));
return result;
}

QRect CannonField::barrierRect() const
{
return QRect(145, height() - 100, 15, 99);
}

bool CannonField::barrelHit(const QPoint &pos) const
{
QMatrix matrix;
matrix.translate(0, height());
matrix.rotate(-currentAngle);
matrix = matrix.inverted();
return barrelRect.contains(matrix.map(pos));
}

bool CannonField::isShooting() const
{
return autoShootTimer->isActive();
}

QSize CannonField::sizeHint() const
{
return QSize(400, 300);
}

lvlina_r
جمعه 22 خرداد 1388, 17:07 عصر
connect(B1->Shoot, SIGNAL(clicked()),
this, SLOT(fire(B1)));


void GameBoard::fire(Player * B)
{
if (cannonField->gameOver() || cannonField->isShooting())
return;
B->shotsLeft->display(B->shotsLeft->intValue() - 1);
cannonField->shoot();
}
آیا کد بالا درسته، یعنی ای connect باعث می شه slot با پارامتر B1 به fire ()بره؟؟؟؟

حامد مصافی
یک شنبه 24 خرداد 1388, 12:04 عصر
خیر، امضاها یکسان نیستند؛ نام پارامتر نباید قید شود.

nasrin55
شنبه 13 تیر 1388, 09:13 صبح
کسی میدونه که تابع setsizepolicy دقیقا چه کاری را انجام میده؟
و متغیرهای درونش چه فایده ای دارند؟
من توی یه مثال این خط را حذف کردم ولی برنامه هیچ تغییری نکرد؟


label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);

پس گذاشتن اون چه فایده ای داره؟؟

حامد مصافی
دوشنبه 15 تیر 1388, 09:56 صبح
رفتار پیش فرض ظاهر شی را تغییر می دهد.

برای مثال اگر شما یک لیبل را به همراه یک textbox در یک VerticalLayout قرار دهید به طور پیش فرض هر کدام از آنها نصف فضای موجود را در اختیار خواهند گرفت. به همین دلیل نیازمند خطی مانند خط فوق خواهید بود. برای مشاهده نتیجه حاصل از حذف خط فوق فرم را کمی بزرگ تر کنید.
برای مشاهده جز خصوصیات QSizePolicy این لینک (http://doc.trolltech.com/3.3/qsizepolicy.html#SizeType-enum)را ببینید.

Nima_NF
دوشنبه 15 تیر 1388, 12:21 عصر
دوستان لطفا سوالات خود را در تاپیک های جداگانه و با عنوان مناسب بپرسید. کل این بخش برای سوالات Qt هست.

موفق باشید