C++ Don';我不懂Qt-ampersand&;按位AND操作:if(ev->;按钮()&Qt::RightButton)
我有以下代码:C++ Don';我不懂Qt-ampersand&;按位AND操作:if(ev->;按钮()&Qt::RightButton),c++,qt,C++,Qt,我有以下代码: void OpenGLRenderer::mouseMoveEvent(QMouseEvent *ev) { //... if(ev->buttons() & Qt::RightButton) { if(ev->modifiers() & Qt::ShiftModifier) { // ... } else {
void OpenGLRenderer::mouseMoveEvent(QMouseEvent *ev)
{
//...
if(ev->buttons() & Qt::RightButton)
{
if(ev->modifiers() & Qt::ShiftModifier)
{
// ...
}
else
{
// ...
}
}
}
我不明白符号
和比较是如何工作的。和
是否有点像和
操作?语句ev->buttons()&Qt::RightButton
如何工作?在返回语句ev->buttons()
/ev->modifiers()
和Qt::RightButton
/
后面有一个数值
为了理解事物是如何工作的,您需要熟悉enum
s,以及真正简洁的QFlags
,它允许您轻松组合多个数值(标志)以创建一个复杂的数值
让我们看一下鼠标按钮:
Qt::NoButton 0x00000000 The button state does not refer to any button (see QMouseEvent::button()).
Qt::LeftButton 0x00000001 The left button is pressed, or an event refers to the left button. (The left button may be the right button on left-handed mice.)
Qt::RightButton 0x00000002 The right button.
Qt::MidButton 0x00000004 The middle button.
Qt::MiddleButton MidButton The middle button.
Qt::XButton1 0x00000008 The first X button.
Qt::XButton2 0x00000010 The second X button.
您可能会注意到,这些值不是连续的,并且缺少一些值。例如,3、5、6等在哪里。?假设您想要处理同时按下左右按钮的情况
在这些数字(十六进制)后面是简单的二进制数(0和1)。如果我们对0x01和0x02应用逻辑OR,则得到0x03:
0x01 | 0x02 = 0x03
如果我们把这些数字看作0和1,我们就有了
0x01 (hex) = 01 (bin)
0x02 (hex) = 10 (bin)
0x03 (hex) = 11 (bin)
正如您所看到的,由于逻辑OR,我们将0x01中的1和0x02中的1组合为一个11,即0x03
现在让我们把事情颠倒过来,取0x03,看看如果ev->buttons()
返回它会发生什么。如果该函数返回此结果,我们知道0x01(左)和0x02(右)当前都被按下。为什么?因为枚举中的值没有其他组合创建0x03!如果我们添加逻辑AND运算符,我们可以将If
条件重写如下(仅使用数值)
但是0x03&0x02
的结果是什么?这是0x02
,这是因为在二进制级别上
11
AND 10
-------
10
因为1和1是1(第一列),但1和0是0(第二列)。如果我们把它翻译成一句话,我们就有了“如果右键当前按下了,那么做…”
让我们做一个更复杂的例子,按下右键、左键和中键(0x01、0x02和0x04)
如果我们想要一个If
语句,它的主体只有在按下右键和中键时才被输入,我们需要做一些计算(同样;)。首先,我们需要得到一个值,该值告诉我们两个必需的按钮都已按下:
010 (right button)
OR 100 (middle button)
------
110 (bin) = 0x06 (hex) (yet another of the missing values in the enumeration above!)
接下来,我们需要将该组合放在ev->buttons()
的return语句中,在本例中,该语句返回0x07(以上三个按钮全部按下):
如果我们把它放在If
条件下
if (ev->buttons() & (Qt::MidButton | Qt::RightButton)
{
// do something
}
显然,如果ev->buttons()
返回类似Qt::RightButton | Qt::XButton1
(无论XButton是什么):D)我们的if
条件将失败。为什么?因为
0010 (Qt::RightButton)
OR 1000 (Qt::XButton1)
-------
1010
结合对Qt::MidButton | Qt::RightButton
的检查
1010 (Qt::RightButton | Qt::XButton1)
AND 0110 (Qt::RightButton | Qt::MidButton)
--------
0010 (Qt::RightButton)
上面的内容可能有点奇怪,但它告诉我们,按下的右键是连接这两个按钮的唯一东西,X键和中间键显然不匹配,因此我们的if
条件将失败
现在,如果你想在这两种情况下都检查正确的按钮,你就可以开始了
1010 (Qt::RightButton | Qt::XButton1)
AND 0010 (Qt::RightButton)
--------
0010 (Qt::RightButton)
以及
0110 (Qt::RightButton | Qt::MidButton)
AND 0010 (Qt::RightButton)
--------
0010 (Qt::RightButton)
另一方面,如果ev->buttons()
仅返回Qt::MidButton
,但您使用AND操作符检查Qt::RightButton
,则会得到
0100 (Qt::MidButton)
AND 0010 (Qt::RightButton)
--------
0000
在C/C++的逻辑中,0的数值与布尔值false
相同,因此不会输入if
的主体
您也可以将相同的逻辑应用到Qt中的所有标志。感谢您的详细介绍@用户3405291希望不是太多D
1010 (Qt::RightButton | Qt::XButton1)
AND 0010 (Qt::RightButton)
--------
0010 (Qt::RightButton)
0110 (Qt::RightButton | Qt::MidButton)
AND 0010 (Qt::RightButton)
--------
0010 (Qt::RightButton)
0100 (Qt::MidButton)
AND 0010 (Qt::RightButton)
--------
0000