UI效果(7): Button的那点事_02

本文深入探讨了Android Button组件的交互事件,包括点击事件、长按事件及触摸事件的实现与应用,通过实例展示了如何分别处理这些事件,并解决了长按事件触发点击事件的问题。

如果你对UI效果(4): Button的那点事_01感兴趣,可以看看。

该篇博客,分享Button的绑定事件如OnTouchListener、OnCliskListener、OnLongClickListener以及注意事项。


单击事件很简单,这里只说一个问题:isPressed()方法。

       /**
	 * 点击事件
	 * 
	 * @author mark
	 * 
	 */
	final class ClickListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case BTN:
				if (v.isPressed()) {
					btn.setText("单击按钮成功!");
				} else {
					btn.setBackgroundColor(Color.BLUE);
				}
				/*if (!v.isPressed()) {
					btn.setBackgroundColor(Color.BLUE);
				}*/
				break;
			}
		}
	}

点击Button可以触发该事件,if (v.isPressed()) 下面的代码可以执行,但是如 else 后面的或者注释掉的 if(! v.isPressed()) 代码不会被执行。

如果你想捕捉Button的按下与弹起的动作,需要实现OnTouchListener接口。最后再说这个问题

在开发中需要将长按事件如单击事件一起使用,现在我们去实现。写长按事件的代码:

       /**
	 * 长按事件
	 * 
	 * @author mark
	 * 
	 */
	final class LongListener implements OnLongClickListener {

		@Override
		public boolean onLongClick(View v) {
			btn.setText("长按按钮成功!");
			return false;
		}
	}
为Button设置事件监听:

btn.setOnClickListener(new ClickListener());
btn.setOnLongClickListener(new LongListener());
运行之后会发现,长按该Button不仅可以触发长按事件,而且还会触发单击事件,怎么办?

很简单,那就是在OnLongClickListener 事件中处理事件之后,告诉其它事件(这里是单击事件onClick)不要再来参与即可。修改代码如下:

       /**
	 * 长按事件
	 * 
	 * @author mark
	 * 
	 */
	final class LongListener implements OnLongClickListener {

		@Override
		public boolean onLongClick(View v) {
			btn.setText("长按按钮成功!");
			// return false;
			return true;
		}
	}

可以看出,单击事件与长按事件分开了。
最后,我们讨论一下如何捕捉Button 的按下与弹起事件。实现代码:

       /**
	 * 触摸事件
	 * 
	 * @author mark
	 * 
	 */
	final class TouchListener implements OnTouchListener {

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			if (event.getAction() == KeyEvent.ACTION_DOWN) {
				btn.setText("已经按下按钮");
			}
			if (event.getAction() == KeyEvent.ACTION_UP) {
				btn.setText("按钮已经弹起");
			}
			return true;// 返回true的话,单击事件、长按事件不可以被触发
			// return false;
		}
	}
完整代码实例:

package mark.zhang;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.LinearLayout;

public class TestActivity extends Activity {
	private static final int BTN = 0x10;

	private Button btn = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 必须先装载该布局文件,否则报空指针异常
		setContentView(R.layout.main);
		LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
		// 布局参数设定
		LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(120, 50);
		lp.gravity = Gravity.CENTER;
		// 创建Button并设置参数
		btn = new Button(this);
		btn.setText("Click me");
		btn.setId(BTN);
		btn.setLayoutParams(lp);
		// 加入当前视图
		ll.addView(btn);
		// 为Button设置监听器
		btn.setOnClickListener(new ClickListener());
		btn.setOnTouchListener(new TouchListener());
		btn.setOnLongClickListener(new LongListener());
	}

	/**
	 * 点击事件
	 * 
	 * @author mark
	 * 
	 */
	final class ClickListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case BTN:
				if (v.isPressed()) {
					btn.setText("单击按钮成功!");
					Log.d("mark", "onclick");
				} else {
					btn.setBackgroundColor(Color.BLUE);
				}
				/*
				 * if (!v.isPressed()) { btn.setBackgroundColor(Color.BLUE); }
				 */
				break;
			}
		}
	}

	/**
	 * 长按事件
	 * 
	 * @author mark
	 * 
	 */
	final class LongListener implements OnLongClickListener {

		@Override
		public boolean onLongClick(View v) {
			btn.setText("长按按钮成功!");
			// return false;
			return true;
		}
	}

	/**
	 * 触摸事件
	 * 
	 * @author mark
	 * 
	 */
	final class TouchListener implements OnTouchListener {

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			if (event.getAction() == KeyEvent.ACTION_DOWN) {
				btn.setText("已经按下按钮");
			}
			if (event.getAction() == KeyEvent.ACTION_UP) {
				btn.setText("按钮已经弹起");
			}
			return true;// 返回true的话,单击事件、长按事件不可以被触发
			// return false;
		}
	}
}





#include "mainwindow.h" #include "ui_mainwindow.h" #include <QKeyEvent> #include <QDebug> #include <QWidget> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); ui->setupUi(this); this->setWindowTitle("计算器2.0"); //按钮上放图片 QIcon con("D:\\qt text\\textalg\\x.PNG.png"); ui->delButton->setIcon(con); connect(ui->addButton,&QPushButton::clicked, this,&MainWindow::on_addButton_clicked); connect(ui->equalButton,&QPushButton::clicked, this,&MainWindow::on_equalButton_clicked); connect(ui->delButton,&QPushButton::clicked, this,&MainWindow::on_delButton_clicked); connect(ui->mulButton,&QPushButton::clicked, this,&MainWindow::on_mulButton_clicked); connect(ui->subButton,&QPushButton::clicked, this,&MainWindow::on_subButton_clicked); connect(ui->divButton,&QPushButton::clicked, this,&MainWindow::on_divButton_clicked); connect(ui->onwButton,&QPushButton::clicked, this,&MainWindow::on_onwButton_clicked); connect(ui->twoButton,&QPushButton::clicked, this,&MainWindow::on_twoButton_clicked); connect(ui->threeButton,&QPushButton::clicked, this,&MainWindow::on_threeButton_clicked); connect(ui->fourButton,&QPushButton::clicked, this,&MainWindow::on_fourButton_clicked); connect(ui->fiveButton,&QPushButton::clicked, this,&MainWindow::on_fiveButton_clicked); connect(ui->sixButton,&QPushButton::clicked, this,&MainWindow::on_sixButton_clicked); connect(ui->sevenButton,&QPushButton::clicked, this,&MainWindow::on_sevenButton_clicked); connect(ui->nineButton,&QPushButton::clicked, this,&MainWindow::on_nineButton_clicked); connect(ui->eightButton,&QPushButton::clicked, this,&MainWindow::on_eightButton_clicked); connect(ui->zeroButton_,&QPushButton::clicked, this,&MainWindow::on_zeroButton__clicked); connect(ui->decButton,&QPushButton::clicked,this,&MainWindow::on_decButton_clicked); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_onwButton_clicked() { expression+="1"; ui->lineEdit->setText(expression); } void MainWindow::on_zeroButton__clicked() { expression+="0"; ui->lineEdit->setText(expression); } void MainWindow::on_liftButton_clicked() { expression+="("; ui->lineEdit->setText(expression); } void MainWindow::on_rightButton_clicked() { expression+=")"; ui->lineEdit->setText(expression); } void MainWindow::on_twoButton_clicked() { expression+="2"; ui->lineEdit->setText(expression); } void MainWindow::on_threeButton_clicked() { expression+="3"; ui->lineEdit->setText(expression); } void MainWindow::on_fourButton_clicked() { expression+="4"; ui->lineEdit->setText(expression); } void MainWindow::on_fiveButton_clicked() { expression+="5"; ui->lineEdit->setText(expression); } void MainWindow::on_sixButton_clicked() { expression+="6"; ui->lineEdit->setText(expression); } void MainWindow::on_sevenButton_clicked() { expression+="7"; ui->lineEdit->setText(expression); } void MainWindow::on_eightButton_clicked() { expression+="8"; ui->lineEdit->setText(expression); } void MainWindow::on_nineButton_clicked() { expression+="9"; ui->lineEdit->setText(expression); } void MainWindow::on_addButton_clicked() { expression+="+"; ui->lineEdit->setText(expression); } void MainWindow::on_subButton_clicked() { expression+="-"; ui->lineEdit->setText(expression); } void MainWindow::on_mulButton_clicked() { expression+="*"; ui->lineEdit->setText(expression); } void MainWindow::on_divButton_clicked() { expression+="/"; ui->lineEdit->setText(expression); } void MainWindow::on_delButton_clicked() { expression.chop(1); ui->lineEdit->setText(expression); } void MainWindow::on_decButton_clicked() { expression+='.'; ui->lineEdit->setText(expression); } void MainWindow::on_equalButton_clicked() { // 获取表达式 QString expr = ui->lineEdit->text(); // 检查表达式是否为空 if (expr.isEmpty()) { ui->lineEdit->setText("Error: Empty expression"); return; } // 解析和计算表达式 double result = evaluateExpression(expr); // 显示结果 ui->lineEdit->setText(QString::number(result)); } double MainWindow::evaluateExpression(const QString &expr) { // 定义运算符优先级 QMap<QChar, int> precedence; precedence['+'] = 1; precedence['-'] = 1; precedence['*'] = 2; precedence['/'] = 2; // 操作数栈 QStack<double> values; // 运算符栈 QStack<QChar> ops; int i = 0; while (i < expr.length()) { QChar c = expr[i]; if (c.isDigit() || c == '.') { // 解析数字(包括小数) double val = 0; int j = i; bool hasDecimal = false; // 判断小数错误 while (j < expr.length() && (expr[j].isDigit() || expr[j] == '.')) { if (expr[j] == '.') { if (hasDecimal) { // 多个小数,非法表达式 return 0; } hasDecimal = true;} j++;} // 提取数字字符串 QString numStr = expr.mid(i, j - i); bool ok; val = numStr.toDouble(&ok); if (!ok) { return 0;} // 转换失败 values.push(val); i = j;} else if (c == '(') { // 左括号直接入栈 ops.push(c); i++;} else if (c == ')') { // 右括号,弹出运算符直到遇到左括号 while (!ops.isEmpty() && ops.top() != '(') { double val2 = values.pop(); double val1 = values.pop(); QChar op = ops.pop(); double res = applyOperator(val1, val2, op); values.push(res);} if (!ops.isEmpty()) { ops.pop();} // 弹出左括号 i++;} else if (precedence.contains(c)) { // 处理运算符 while (!ops.isEmpty() && ops.top() != '(' && precedence[ops.top()] >= precedence[c]) { double val2 = values.pop(); double val1 = values.pop(); QChar op = ops.pop(); double res = applyOperator(val1, val2, op); values.push(res);} ops.push(c); i++;} else { // 非法字符 return 0;} } // 处理剩余的运算符 while (!ops.isEmpty()) { double val2 = values.pop(); double val1 = values.pop(); QChar op = ops.pop(); double res = applyOperator(val1, val2, op); values.push(res); } return values.pop(); } double MainWindow::applyOperator(double a, double b, QChar op) { switch (op.toLatin1()) { case '+': return a + b; case '-': return a - b; case '*': return a * b; case '/': if (b == 0) { // 除以零错误 return 0; } else { double x=a/b; return x; } default: return 0; } } void MainWindow::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { on_equalButton_clicked(); // 直接调用等号按钮的槽函数 } else { QWidget::keyPressEvent(event); // 其他按键交给父类处理 } } void MainWindow::on_clearButton_clicked() { expression.clear(); ui->lineEdit->clear(); } 为什么clear无法清除字符串
06-27
### 3.1 常见原因分析 在Qt C++中,调用 `expression.clear()` 和 `ui->lineEdit->clear()` 无法清除表达式字符串的问题,可能由多种因素导致。 若 `expression` 是一个 `QString` 或 `std::string` 类型的变量,并未与 `QLineEdit` 控件绑定,则调用 `expression.clear()` 仅会清空该局部变量的内容,而不会影响界面上显示的数据。这种情况常见于开发者误认为控件内容会自动同步更新[^1]。 ```cpp QString expression = ui->lineEdit->text(); expression.clear(); // 仅清空局部变量,不会影响 QLineEdit 的内容 ``` 此外,如果 `ui->lineEdit` 指针为空或未正确初始化,调用 `lineEdit->clear()` 将不会产生任何效果。这种问题通常出现在UI组件未正确加载或指针管理不当的情况下[^2]。 ```cpp if (ui->lineEdit == nullptr) { // 此时调用 clear() 不会生效 } ``` ### 3.2 多线程环境下的 UI 更新限制 Qt 的 UI 操作必须在主线程(即 GUI 线程)中执行。如果尝试在子线程中调用 `lineEdit->clear()`,则可能导致界面状态不一致,甚至程序崩溃。为了安全地跨线程更新 UI,应使用 `QMetaObject::invokeMethod` 或信号/槽机制来调度操作到主线程[^3]。 ```cpp QMetaObject::invokeMethod(ui->lineEdit, "clear", Qt::QueuedConnection); ``` ### 3.3 数据绑定与事件循环延迟 某些情况下,即使调用了 `lineEdit->clear()`,由于事件循环被阻塞或数据源未同步更新,界面可能不会立即反映更改。例如,在一个耗时操作中频繁调用 `clear()` 而没有主动刷新控件,可能导致界面更新延迟。此时应考虑使用 `QApplication::processEvents()` 强制刷新界面状态[^4]。 ```cpp ui->lineEdit->clear(); QApplication::processEvents(); // 强制刷新界面 ``` ### 3.4 内存管理与悬空指针 如果 `ui->lineEdit` 所属的父窗口已被释放,但其指针仍未置空,则再次调用 `clear()` 将导致未定义行为。此类问题常见于动态创建和销毁控件的过程中,尤其是在使用手动内存管理时[^5]。 ```cpp QWidget* parentWidget = new QWidget; QLineEdit* lineEdit = new QLineEdit(parentWidget); delete parentWidget; // parentWidget 被删除,lineEdit 成为悬空指针 lineEdit->clear(); // 未定义行为 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值