[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-games-devel
Subject:    [Kde-games-devel] KAction and KAccel in games
From:       Andreas Beckermann <b_mann () gmx ! de>
Date:       2002-05-17 19:22:04
[Download RAW message or body]

Hi all
after some discussion on kde-devel I figured out that KAccel is kind of 
obsolete. One should use KAction instead. 
Well, this is one of the not-documented parts on the KDE project and since 
there are a few special cases in games on this subject I decided to write my 
experiences from down.
The file is attached (plain text), I hope you can use it.

Once I find the time I'll also put this on games.kde.org

CU
Andi
["kaction_and_kaccel_in_games" (text/plain)]

KAction and KAccel in games
---------------------------

First of all: don't use KAccel. You are meant to use KAction whenever possible,
since it provides better configuratoin abilities.
There are plans to remove direct configuration of KAccel - so simply use
KAction, it does the rest.

You also should not hardcode keys. For example don't use something like

void MyWidget::keyPressedEvent(QKeyEvent* e)
{
 if (e->key() == Qt::Key_Up) {
	doSomething();
 }
}

or the same using KAccel.
This is not the way to go, as you should allow the user to change the keys for
every event. 
Instead you can simply use KAction for keys. KAction is not only meant for menu
or toolbar items but for key-only actions, too. Simply use

(void)new KAction(i18n("Move Up"), Qt::Key_Up, this, SLOT(doSomething()),
		actionCollection(), "move_up");

to achieve the above using KAction.

Additional KActionCollection objects
------------------------------------
There are situations, especially in games, where this is not the ideal thing to
do, since you need to have access to KMainWindow::actionCollection() which you
often don't have. If you want to avoid ugly hacks you can just create your own
KActionCollection object:

mActionCollection = new KActionCollection(this);
(void)new KAction(i18n("Move Up"), Qt::Key_Up, this, SLOT(doSomething()),
		mActionCollection, "move_up");

As a side effect you get another section in KKeyDialog::configure() which helps
to logically separate your actions from others.

Different KActions for a single slot
------------------------------------
A few things are left that often come up in games. E.g. think about several
different keys which do slightly the same. For example in a poker game you can
exchange every card - 5 functions that do exactly the same but for a different
card. 
You can either create 5 KAction objects or you can give an integer
parameter to the slot. This is especially *very* useful when you want to define
a dynamic number of actions (think of unit groups in a strategy game for
example). Here is the code:

(void)new KAction(i18n("Exchange Card 1"), Qt::Key_1, this, SLOT(exchangeCard(int)),
		actionCollection(), "exchange {1}");
(void)new KAction(i18n("Exchange Card 2"), Qt::Key_2, this, SLOT(exchangeCard(int)),
		actionCollection(), "exchange {2}");
(void)new KAction(i18n("Exchange Card 3"), Qt::Key_3, this, SLOT(exchangeCard(int)),
		actionCollection(), "exchange {3}");
(void)new KAction(i18n("Exchange Card 4"), Qt::Key_4, this, SLOT(exchangeCard(int)),
		actionCollection(), "exchange {4}");
(void)new KAction(i18n("Exchange Card 5"), Qt::Key_5, this, SLOT(exchangeCard(int)),
		actionCollection(), "exchange {5}");

You can just provide the integer value that gets emitted by KAction in the
name. The number between {} will be given to exchangeCard(int).
(this feature currently applies to HEAD only - will be in KDE 3.1)

key[Release|Press]Event and KAction
-----------------------------------
In another scenario you don't want to rely on the usual keyrepeat rate but
really need to use keyPressEvent() and keyReleasEvent(). This is usually the
case e.g. for a 2d scroller where the player moves forward while an arrow key is
pressed and stops once its released. So you really don't want to use slots. But
you can still use KAction for this:

mAction = new KAction(i18n("Move Left"), Qt::Key_Left, 0, 0, 
		actionCollection(), "move_left");
[...]
and in MyWidget::keyPressedEvent(QKeyEvent* event):
KKey key(event);
if (mAction->shortcut().contains(key)) {
	doSomething();
}

You should use KShortcut::contains() because a KShortcut can have two, not only
one, key sequences assigned.
As you can see from the example above, you don't need to provide a slot/receiver
for a KAction object. Simply passing 0 as receiver/slot disables slots.
Please note that this does not work for KDE 3.0.x but only for KDE >= 3.1 !
key[Press|Release]Event() do not get called in 3.0.x even if there is no slot
assigned to the action.

KKeyDialog and keys without modifier
------------------------------------
In KDE versions < 3.1 there is a bug in KKeyDialog which lets you not assign
letters without modifier key as a shortcut. This is fixed in KDE 3.1 (or
currently HEAD) - if you want the user to assign normal keys in previous
versions you just have to avoid KKeyDialog::configure(). Use:
KKeyDialog dlg(true);
dlg.insert(actionCollection());
dlg.configure(true);
instead of 
KKeyDialog::configure(actionCollection());



_______________________________________________
kde-games-devel mailing list
kde-games-devel@mail.kde.org
http://mail.kde.org/mailman/listinfo/kde-games-devel

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic