UI效果(4): Button的那点事_01

Android UI 实现技巧
本文介绍了一种在Android中实现两个按钮紧挨排列的方法,并展示了如何设置EditText为只读状态及TextView自动链接网页的技术细节。

再这篇博客中,您可以了解一下内容:

<1> 两个Button连在一起效果的实现方法

<2> EditText不可编辑实现,以及注意事项

<3> TextView自动连接web

再看代码之前,先看看效果吧!

运行之后,见下图:


点击save_settings,效果图如下:


再点击cancel_settings,效果图如下:


项目结构图:


效果图点到为止,看源码吧。

1. main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent" android:background="#ff9900">

	<LinearLayout android:layout_width="fill_parent"
		android:id="@+id/linearLayout1" android:layout_height="wrap_content"
		android:gravity="center_horizontal" android:layout_marginTop="5dip">
		<Button android:id="@+id/button_save" android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="save settings"
			android:background="@drawable/btn" style="?android:attr/buttonStyleInset"></Button>
		<Button android:id="@+id/button_cancel" android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="cancel settings"
			android:background="@drawable/btn" android:layout_marginLeft="-1px"
			style="?android:attr/buttonStyleInset"></Button>
	</LinearLayout>
	<!-- android:gravity="top"设置文字显示在顶部,而不是在中间显示文字 -->
	<EditText android:id="@+id/edit" android:layout_width="280dip"
		android:layout_height="180dip" android:layout_marginTop="10dip"
		android:layout_gravity="center_horizontal" android:gravity="top"
		android:hint="waiting for you click..."/>
	<TextView android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:text="@string/myblog"
		android:autoLink="web" android:textSize="20sp" android:textStyle="italic"
		android:layout_marginLeft="20dip" />
</LinearLayout>

在该布局文件中,使用线性布局实现两个Button连在一起的效果,关键是 android:layout_marginLeft="-1px"。可以根据实际情况来决定这个值。

style="?android:attr/buttonStyleInset"是设置Button样式,更多样式设置可以参考sdk的api的android包下面的R.attr.

另外,设置Button有按下的效果,需要为其设置selector,也就是上面xml文件中android:background="@drawable/btn设置。其中btn是drawable下面的一个xml文件。

源码如下:

<?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_pressed="true"
           android:drawable="@drawable/show" /> <!-- pressed -->
     <item android:state_focused="true"
           android:drawable="@drawable/focus" /> <!-- focused -->
     <item android:drawable="@drawable/back" /> <!-- default -->
 </selector>

更多关于selector的信息,可以参阅sdk/resources/tutorials/下面有个Custom Button。

android:autoLink用来设置TextView的超链接。

2. Activity

package mark.zhang;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class TestActivity extends Activity {
	private Button btn_save = null;
	private Button btn_cancel = null;
	private EditText edit = null;
	
	private EvenListener listener = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		init();
		findView();
		setEven();
	}
	
	private void init() {
		listener = new EvenListener();
	}
	
	private void findView() {
		btn_save = (Button) findViewById(R.id.button_save);
		btn_cancel = (Button) findViewById(R.id.button_cancel);
		edit = (EditText) findViewById(R.id.edit);
	}
	
	private void setEven() {
		btn_save.setOnClickListener(listener);
		btn_cancel.setOnClickListener(listener);
	}
	
	final class EvenListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			switch(v.getId()) {
			case R.id.button_save:
				// 改变显示背景图片
				/*btn_save.setBackgroundResource(R.drawable.show);
				btn_cancel.setBackgroundResource(R.drawable.back);*/
				
				// 改变显示文字颜色
				btn_save.setTextColor(Color.RED);
				btn_cancel.setTextColor(Color.BLACK);
				
				// 改变显示字体样式
				/*btn_save.setTypeface(null, Typeface.BOLD);
				btn_cancel.setTypeface(null, Typeface.NORMAL);*/
				
				edit.append("you have selected the 'save_settings' Button!\n");
				edit.append("\n");
				break;
			case R.id.button_cancel:
				/*btn_save.setBackgroundResource(R.drawable.back);
				btn_cancel.setBackgroundResource(R.drawable.show);*/
				
				btn_save.setTextColor(Color.BLACK);
				btn_cancel.setTextColor(Color.RED);
				
				/*btn_cancel.setTypeface(null, Typeface.BOLD);
				btn_save.setTypeface(null, Typeface.NORMAL);*/
				
				edit.append("you have selected the 'cancel_settings' Button!\n");
				edit.append("\n");
				break;
			default:
				break;
			}
		}
	}
}

Java代码很简单,不做说明。

那么,我们来更改代码,使EditText不可以被别人编辑,因为这里不需要去编辑EditText,只是用来显示信息。修改main.xml文件的<EditText></EditText>如下:

<EditText android:id="@+id/edit" android:layout_width="280dip"
		android:layout_height="180dip" android:layout_marginTop="10dip"
		android:layout_gravity="center_horizontal" android:gravity="top"
		android:hint="waiting for you click..."
		android:editable="false"
		android:focusable="false" android:focusableInTouchMode="false"/>

ok,这样edittext就不可以编辑了。

另一种方式就是在代码中,设置其不可获得焦点:

edit.setFocusable(false);
edit.setFocusableInTouchMode(false);

推荐一篇文章  android 如何实现EditText从不可编辑状态变成可变成可编辑状态

但是注意一点:

// edit设置不可以编辑
edit.setFilters(new InputFilter[] { new InputFilter() {

	@Override
	public CharSequence filter(CharSequence source, int start, int end,
		Spanned dest, int dstart, int dend) {
		return source.length() < 1 ? dest.subSequence(dstart, dend)
				: "";
	}
} });
设置该代码之后,EditText不可以添加文字,对于本例子点击save_settings或者cancel_settings不会更新EditText的显示。但是如果在xml文件中不设置:

android:focusable="false"
Edittext还会显示软键盘,所以为了提高用户体验,在不可编辑的状态下就不要让其出现软键盘。


#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、付费专栏及课程。

余额充值