自定义控件_自定义控件下载 - CSDN
精华内容
参与话题
  • Android自定义控件(一)

    千次阅读 2019-03-01 13:11:22
    Android中提供的控件基本可以满足我们日常开发的需求,但是有些需求只凭这里控件的组合并不能满足,我们可以通过写自定义控件来实现各种功能的控件,比如QQ消息右上角红色提示框水波式消失效果。本篇将对Android...

    Android中提供的控件基本可以满足我们日常开发的需求,但是有些需求只凭这里控件的组合并不能满足,我们可以通过写自定义控件来实现各种功能的控件,比如QQ消息右上角红色提示框水波式消失效果。本篇将对Android自定义控件进行基本的讲解,后面还会持续更新。

    自定义控件要求:
         1. 应当遵守Android标准的规范(命名,可配置,事件处理等)。
         2. 在XML布局中可配置控件的属性。
         3. 对交互应当有合适的反馈,比如按下,点击等。
         4. 具有兼容性, Android版本很多,应该具有广泛的适用性。

    自定义控件学习步骤:
      1 .View的工作原理 
      2 .编写View类 
      3.为View类增加属性 
      4 .绘制屏幕 
      5. 响应用户消息 
      6 .自定义回调函数

    自定义控件两种方式:
      1. 继承ViewGroup 

          例如:ViewGroup、LinearLayout、FrameLayout、RelativeLayout等。

      2. 继承View

          例如:View、TextView、ImageView、Button等。

    自定义控件基本绘制原理:
    View的绘制基本上由measure()、layout()、draw()这个三个函数完成

    1.)测量-Measure过程是计算视图大小,View measure过程相关方法主要有三个:

    public final void measure(int widthMeasureSpec, int heightMeasureSpec)  
    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight)  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  

    measure调用onMeasure,onMeasure测量宽度、高度然后调用setMeasureDimension保存测量结果,measure,setMeasureDimension是final类型,view的子类不需要重写,onMeasure在view的子类中重写。

    关于MeasureSpec:

    (1) UPSPECIFIED :未指定模式,父容器对于子容器没有任何限制,子容器想要多大就多大,通常在绘制自定义View时才会用

    (2) EXACTLY:精确值模式,父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间,当控件的layout_width和layout_height属性指定为具体数值或match_parent时为该模式。

    (3) AT_MOST:最大值模式,子容器可以是声明大小内的任意大小,当空间的宽高设置为wrap_content时为该模式

    2.)布局-Layout过程用于设置视图在屏幕中显示的位置,View layout过程相关方法主要要三个:

    public void layout(int l, int t, int r, int b)
    protected boolean setFrame(int left, int top, int right, int bottom)
    protected void onLayout(boolean changed, int left, int top, int right, int bottom)

    layout通过调用setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,onLayout一般只会在自定义ViewGroup中才会使用

    3.)绘制-draw过程主要用于利用前两步得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。

    public void draw(Canvas canvas)
    protected void onDraw(Canvas canvas)

    通过调用draw函数进行视图绘制,在View类中onDraw函数是个空函数,最终的绘制需求需要在自定义的onDraw函数中进行实现,比如ImageView完成图片的绘制,如果自定义ViewGroup这个函数则不需要重载。

    上面对自定义View的流程作了基本的介绍,参考下面两篇博客

    https://www.cnblogs.com/Free-Thinker/p/6113461.html

    http://www.cnblogs.com/whoislcj/p/5708778.html

     

    下面是一个绘制简单百分比的例子

    定义一个继承View的类,重写构造方法,onMeasure,onDraw方法,即可构建一个简单的自定义控件

    SimpleView类代码如下:
     

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
     
    public class SimpleView extends View {
     
        private final static String TAG = SimpleView.class.getSimpleName();
        //画笔
        private Paint mPaint;
        private RectF oval;
     
        public SimpleView(Context context) {
            super(context);
            init();
        }
     
        public SimpleView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init();
        }
     
        public SimpleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
     
        private void init(){
            mPaint = new Paint();
            //设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。
            mPaint.setAntiAlias(true);
            mPaint.setTextSize(30.0f);
            oval=new RectF();
        }
     
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            Log.e(TAG, "onMeasure--widthMode-->" + widthMode);
            switch (widthMode) {
                case MeasureSpec.EXACTLY:
                    //精确值模式,当控件的layout_width和layout_height属性指定为具体数值或match_parent时。
                    break;
                case MeasureSpec.AT_MOST:
                    //最大值模式,当空间的宽高设置为wrap_content时。
                    break;
                case MeasureSpec.UNSPECIFIED:
                    //未指定模式,View想多大就多大,通常在绘制自定义View时才会用。
                    break;
            }
            //取最小边为控件的宽高的最小值
            int minWidth=widthSize>heightSize?heightSize:widthSize;
            setMeasuredDimension(minWidth,minWidth);
        }
     
     
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPaint.setColor(Color.GRAY);
            // FILL填充, STROKE描边,FILL_AND_STROKE填充和描边
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            int with = getWidth();
            int height = getHeight();
            Log.e(TAG, "onDraw---->" + with + "*" + height);
            float radius = with / 4;
            canvas.drawCircle(with / 2, with / 2, radius, mPaint);
            mPaint.setColor(Color.RED);
            oval.set(with / 2 - radius, with / 2 - radius, with / 2
                    + radius, with / 2 + radius);//用于定义的圆弧的形状和大小的界限
            int sweepAngle=120;
            canvas.drawArc(oval, 0, -sweepAngle, true, mPaint);  //根据进度画圆弧
            double percent=sweepAngle/360.0;
            //设置文本颜色
            mPaint.setColor(Color.WHITE);
            //绘制文本百分比数据
            canvas.drawText(String.format("%.2f",percent)+"%",(float)(with/2+radius*Math.cos(sweepAngle*Math.PI/360)/4) 
                    ,(float)(with/2-radius*Math.sin(sweepAngle*Math.PI/360)/3),mPaint);
            canvas.drawText(String.format("%.2f",1-percent)+"%",(float)(with/2-radius*Math.cos(sweepAngle*Math.PI/360)) 
                    ,(float)(with/2+radius*Math.sin(sweepAngle*Math.PI/360)/3),mPaint);
        }
    }

    展开全文
  • C#自定义控件

    千次下载 热门讨论 2020-07-30 23:30:38
    C#自定义控件
  • 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了,回顾一下,我们一共学习了...现在前半部分的承诺已经如约兑现了,那么今天我就要来兑现后面部分的承诺,讲一讲自定义View的实现方法,同时这也是带

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967


    不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了,回顾一下,我们一共学习了LayoutInflater的原理分析、视图的绘制流程、视图的状态及重绘等知识,算是把View中很多重要的知识点都涉及到了。如果你还没有看过我前面的几篇文章,建议先去阅读一下,多了解一些原理方面的东西。


    之前我有承诺过,会在View这个话题上多写几篇博客,讲一讲View的工作原理,以及自定义View的方法。现在前半部分的承诺已经如约兑现了,那么今天我就要来兑现后面部分的承诺,讲一讲自定义View的实现方法,同时这也是带你一步步深入了解View系列的完结篇。


    一些接触Android不久的朋友对自定义View都有一丝畏惧感,总感觉这是一个比较高级的技术,但其实自定义View并不复杂,有时候只需要简单几行代码就可以完成了。


    如果说要按类型来划分的话,自定义View的实现方式大概可以分为三种,自绘控件、组合控件、以及继承控件。那么下面我们就来依次学习一下,每种方式分别是如何自定义View的。


    一、自绘控件


    自绘控件的意思就是,这个View上所展现的内容全部都是我们自己绘制出来的。绘制的代码是写在onDraw()方法中的,而这部分内容我们已经在 Android视图绘制流程完全解析,带你一步步深入了解View(二) 中学习过了。


    下面我们准备来自定义一个计数器View,这个View可以响应用户的点击事件,并自动记录一共点击了多少次。新建一个CounterView继承自View,代码如下所示:

    public class CounterView extends View implements OnClickListener {
    
    	private Paint mPaint;
    	
    	private Rect mBounds;
    
    	private int mCount;
    	
    	public CounterView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    		mBounds = new Rect();
    		setOnClickListener(this);
    	}
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    		super.onDraw(canvas);
    		mPaint.setColor(Color.BLUE);
    		canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
    		mPaint.setColor(Color.YELLOW);
    		mPaint.setTextSize(30);
    		String text = String.valueOf(mCount);
    		mPaint.getTextBounds(text, 0, text.length(), mBounds);
    		float textWidth = mBounds.width();
    		float textHeight = mBounds.height();
    		canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2
    				+ textHeight / 2, mPaint);
    	}
    
    	@Override
    	public void onClick(View v) {
    		mCount++;
    		invalidate();
    	}
    
    }

    可以看到,首先我们在CounterView的构造函数中初始化了一些数据,并给这个View的本身注册了点击事件,这样当CounterView被点击的时候,onClick()方法就会得到调用。而onClick()方法中的逻辑就更加简单了,只是对mCount这个计数器加1,然后调用invalidate()方法。通过 Android视图状态及重绘流程分析,带你一步步深入了解View(三) 这篇文章的学习我们都已经知道,调用invalidate()方法会导致视图进行重绘,因此onDraw()方法在稍后就将会得到调用。


    既然CounterView是一个自绘视图,那么最主要的逻辑当然就是写在onDraw()方法里的了,下面我们就来仔细看一下。这里首先是将Paint画笔设置为蓝色,然后调用Canvas的drawRect()方法绘制了一个矩形,这个矩形也就可以当作是CounterView的背景图吧。接着将画笔设置为黄色,准备在背景上面绘制当前的计数,注意这里先是调用了getTextBounds()方法来获取到文字的宽度和高度,然后调用了drawText()方法去进行绘制就可以了。


    这样,一个自定义的View就已经完成了,并且目前这个CounterView是具备自动计数功能的。那么剩下的问题就是如何让这个View在界面上显示出来了,其实这也非常简单,我们只需要像使用普通的控件一样来使用CounterView就可以了。比如在布局文件中加入如下代码:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <com.example.customview.CounterView
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true" />
    
    </RelativeLayout>

    可以看到,这里我们将CounterView放入了一个RelativeLayout中,然后可以像使用普通控件来给CounterView指定各种属性,比如通过layout_width和layout_height来指定CounterView的宽高,通过android:layout_centerInParent来指定它在布局里居中显示。只不过需要注意,自定义的View在使用的时候一定要写出完整的包名,不然系统将无法找到这个View。


    好了,就是这么简单,接下来我们可以运行一下程序,并不停地点击CounterView,效果如下图所示。




    怎么样?是不是感觉自定义View也并不是什么高级的技术,简单几行代码就可以实现了。当然了,这个CounterView功能非常简陋,只有一个计数功能,因此只需几行代码就足够了,当你需要绘制比较复杂的View时,还是需要很多技巧的。


    二、组合控件


    组合控件的意思就是,我们并不需要自己去绘制视图上显示的内容,而只是用系统原生的控件就好了,但我们可以将几个系统原生的控件组合到一起,这样创建出的控件就被称为组合控件。


    举个例子来说,标题栏就是个很常见的组合控件,很多界面的头部都会放置一个标题栏,标题栏上会有个返回按钮和标题,点击按钮后就可以返回到上一个界面。那么下面我们就来尝试去实现这样一个标题栏控件。


    新建一个title.xml布局文件,代码如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#ffcb05" >
    
        <Button
            android:id="@+id/button_left"
            android:layout_width="60dp"
            android:layout_height="40dp"
            android:layout_centerVertical="true"
            android:layout_marginLeft="5dp"
            android:background="@drawable/back_button"
            android:text="Back"
            android:textColor="#fff" />
    
        <TextView
            android:id="@+id/title_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="This is Title"
            android:textColor="#fff"
            android:textSize="20sp" />
    
    </RelativeLayout>

    在这个布局文件中,我们首先定义了一个RelativeLayout作为背景布局,然后在这个布局里定义了一个Button和一个TextView,Button就是标题栏中的返回按钮,TextView就是标题栏中的显示的文字。


    接下来创建一个TitleView继承自FrameLayout,代码如下所示:

    public class TitleView extends FrameLayout {
    
    	private Button leftButton;
    
    	private TextView titleText;
    
    	public TitleView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		LayoutInflater.from(context).inflate(R.layout.title, this);
    		titleText = (TextView) findViewById(R.id.title_text);
    		leftButton = (Button) findViewById(R.id.button_left);
    		leftButton.setOnClickListener(new OnClickListener() {
    			@Override
    			public void onClick(View v) {
    				((Activity) getContext()).finish();
    			}
    		});
    	}
    
    	public void setTitleText(String text) {
    		titleText.setText(text);
    	}
    
    	public void setLeftButtonText(String text) {
    		leftButton.setText(text);
    	}
    
    	public void setLeftButtonListener(OnClickListener l) {
    		leftButton.setOnClickListener(l);
    	}
    
    }

    TitleView中的代码非常简单,在TitleView的构建方法中,我们调用了LayoutInflater的inflate()方法来加载刚刚定义的title.xml布局,这部分内容我们已经在 Android LayoutInflater原理分析,带你一步步深入了解View(一) 这篇文章中学习过了。


    接下来调用findViewById()方法获取到了返回按钮的实例,然后在它的onClick事件中调用finish()方法来关闭当前的Activity,也就相当于实现返回功能了。


    另外,为了让TitleView有更强地扩展性,我们还提供了setTitleText()、setLeftButtonText()、setLeftButtonListener()等方法,分别用于设置标题栏上的文字、返回按钮上的文字、以及返回按钮的点击事件。


    到了这里,一个自定义的标题栏就完成了,那么下面又到了如何引用这个自定义View的部分,其实方法基本都是相同的,在布局文件中添加如下代码:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <com.example.customview.TitleView
            android:id="@+id/title_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </com.example.customview.TitleView>
    
    </RelativeLayout>

    这样就成功将一个标题栏控件引入到布局文件中了,运行一下程序,效果如下图所示:




    现在点击一下Back按钮,就可以关闭当前的Activity了。如果你想要修改标题栏上显示的内容,或者返回按钮的默认事件,只需要在Activity中通过findViewById()方法得到TitleView的实例,然后调用setTitleText()、setLeftButtonText()、setLeftButtonListener()等方法进行设置就OK了。


    三、继承控件


    继承控件的意思就是,我们并不需要自己重头去实现一个控件,只需要去继承一个现有的控件,然后在这个控件上增加一些新的功能,就可以形成一个自定义的控件了。这种自定义控件的特点就是不仅能够按照我们的需求加入相应的功能,还可以保留原生控件的所有功能,比如 Android PowerImageView实现,可以播放动画的强大ImageView 这篇文章中介绍的PowerImageView就是一个典型的继承控件。


    为了能够加深大家对这种自定义View方式的理解,下面我们再来编写一个新的继承控件。ListView相信每一个Android程序员都一定使用过,这次我们准备对ListView进行扩展,加入在ListView上滑动就可以显示出一个删除按钮,点击按钮就会删除相应数据的功能。


    首先需要准备一个删除按钮的布局,新建delete_button.xml文件,代码如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <Button xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/delete_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/delete_button" >
    
    </Button>

    这个布局文件很简单,只有一个按钮而已,并且我们给这个按钮指定了一张删除背景图。


    接着创建MyListView继承自ListView,这就是我们自定义的View了,代码如下所示:

    public class MyListView extends ListView implements OnTouchListener,
    		OnGestureListener {
    
    	private GestureDetector gestureDetector;
    
    	private OnDeleteListener listener;
    
    	private View deleteButton;
    
    	private ViewGroup itemLayout;
    
    	private int selectedItem;
    
    	private boolean isDeleteShown;
    
    	public MyListView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		gestureDetector = new GestureDetector(getContext(), this);
    		setOnTouchListener(this);
    	}
    
    	public void setOnDeleteListener(OnDeleteListener l) {
    		listener = l;
    	}
    
    	@Override
    	public boolean onTouch(View v, MotionEvent event) {
    		if (isDeleteShown) {
    			itemLayout.removeView(deleteButton);
    			deleteButton = null;
    			isDeleteShown = false;
    			return false;
    		} else {
    			return gestureDetector.onTouchEvent(event);
    		}
    	}
    
    	@Override
    	public boolean onDown(MotionEvent e) {
    		if (!isDeleteShown) {
    			selectedItem = pointToPosition((int) e.getX(), (int) e.getY());
    		}
    		return false;
    	}
    
    	@Override
    	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
    			float velocityY) {
    		if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) {
    			deleteButton = LayoutInflater.from(getContext()).inflate(
    					R.layout.delete_button, null);
    			deleteButton.setOnClickListener(new OnClickListener() {
    				@Override
    				public void onClick(View v) {
    					itemLayout.removeView(deleteButton);
    					deleteButton = null;
    					isDeleteShown = false;
    					listener.onDelete(selectedItem);
    				}
    			});
    			itemLayout = (ViewGroup) getChildAt(selectedItem
    					- getFirstVisiblePosition());
    			RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
    					LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    			params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
    			params.addRule(RelativeLayout.CENTER_VERTICAL);
    			itemLayout.addView(deleteButton, params);
    			isDeleteShown = true;
    		}
    		return false;
    	}
    
    	@Override
    	public boolean onSingleTapUp(MotionEvent e) {
    		return false;
    	}
    
    	@Override
    	public void onShowPress(MotionEvent e) {
    
    	}
    
    	@Override
    	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
    			float distanceY) {
    		return false;
    	}
    
    	@Override
    	public void onLongPress(MotionEvent e) {
    	}
    	
    	public interface OnDeleteListener {
    
    		void onDelete(int index);
    
    	}
    
    }

    由于代码逻辑比较简单,我就没有加注释。这里在MyListView的构造方法中创建了一个GestureDetector的实例用于监听手势,然后给MyListView注册了touch监听事件。然后在onTouch()方法中进行判断,如果删除按钮已经显示了,就将它移除掉,如果删除按钮没有显示,就使用GestureDetector来处理当前手势。


    当手指按下时,会调用OnGestureListener的onDown()方法,在这里通过pointToPosition()方法来判断出当前选中的是ListView的哪一行。当手指快速滑动时,会调用onFling()方法,在这里会去加载delete_button.xml这个布局,然后将删除按钮添加到当前选中的那一行item上。注意,我们还给删除按钮添加了一个点击事件,当点击了删除按钮时就会回调onDeleteListener的onDelete()方法,在回调方法中应该去处理具体的删除操作。


    好了,自定义View的功能到此就完成了,接下来我们需要看一下如何才能使用这个自定义View。首先需要创建一个ListView子项的布局文件,新建my_list_view_item.xml,代码如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:descendantFocusability="blocksDescendants"
        android:orientation="vertical" >
    
        <TextView
            android:id="@+id/text_view"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:layout_centerVertical="true"
            android:gravity="left|center_vertical"
            android:textColor="#000" />
    
    </RelativeLayout>
    然后创建一个适配器MyAdapter,在这个适配器中去加载my_list_view_item布局,代码如下所示:
    public class MyAdapter extends ArrayAdapter<String> {
    
    	public MyAdapter(Context context, int textViewResourceId, List<String> objects) {
    		super(context, textViewResourceId, objects);
    	}
    
    	@Override
    	public View getView(int position, View convertView, ViewGroup parent) {
    		View view;
    		if (convertView == null) {
    			view = LayoutInflater.from(getContext()).inflate(R.layout.my_list_view_item, null);
    		} else {
    			view = convertView;
    		}
    		TextView textView = (TextView) view.findViewById(R.id.text_view);
    		textView.setText(getItem(position));
    		return view;
    	}
    
    }
    到这里就基本已经完工了,下面在程序的主布局文件里面引入MyListView这个控件,如下所示:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <com.example.customview.MyListView
            android:id="@+id/my_list_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </com.example.customview.MyListView>
    
    </RelativeLayout>
    最后在Activity中初始化MyListView中的数据,并处理了onDelete()方法的删除逻辑,代码如下所示:
    public class MainActivity extends Activity {
    
    	private MyListView myListView;
    
    	private MyAdapter adapter;
    
    	private List<String> contentList = new ArrayList<String>();
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		requestWindowFeature(Window.FEATURE_NO_TITLE);
    		setContentView(R.layout.activity_main);
    		initList();
    		myListView = (MyListView) findViewById(R.id.my_list_view);
    		myListView.setOnDeleteListener(new OnDeleteListener() {
    			@Override
    			public void onDelete(int index) {
    				contentList.remove(index);
    				adapter.notifyDataSetChanged();
    			}
    		});
    		adapter = new MyAdapter(this, 0, contentList);
    		myListView.setAdapter(adapter);
    	}
    
    	private void initList() {
    		contentList.add("Content Item 1");
    		contentList.add("Content Item 2");
    		contentList.add("Content Item 3");
    		contentList.add("Content Item 4");
    		contentList.add("Content Item 5");
    		contentList.add("Content Item 6");
    		contentList.add("Content Item 7");
    		contentList.add("Content Item 8");
    		contentList.add("Content Item 9");
    		contentList.add("Content Item 10");
    		contentList.add("Content Item 11");
    		contentList.add("Content Item 12");
    		contentList.add("Content Item 13");
    		contentList.add("Content Item 14");
    		contentList.add("Content Item 15");
    		contentList.add("Content Item 16");
    		contentList.add("Content Item 17");
    		contentList.add("Content Item 18");
    		contentList.add("Content Item 19");
    		contentList.add("Content Item 20");
    	}
    
    }

    这样就把整个例子的代码都完成了,现在运行一下程序,会看到MyListView可以像ListView一样,正常显示所有的数据,但是当你用手指在MyListView的某一行上快速滑动时,就会有一个删除按钮显示出来,如下图所示:



    点击一下删除按钮就可以将第6行的数据删除了。此时的MyListView不仅保留了ListView原生的所有功能,还增加了一个滑动进行删除的功能,确实是一个不折不扣的继承控件。

    到了这里,我们就把自定义View的几种实现方法全部讲完了,虽然每个例子都很简单,但是万变不离其宗,复杂的View也是由这些简单的原理堆积出来的。经过了四篇文章的学习,相信每个人对View的理解都已经较为深入了,那么带你一步步深入了解View系列的文章就到此结束,感谢大家有耐心看到最后。

    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • C# 自定义用户控件 此处为转载文章,用于记录自我学习过程,原文链接地址http://blog.csdn.net/xiongxuanwen/article/details/2605109 上篇:控件制作 本例是制作一个简单的自定义控件,然后用一个简单的测试...
    C# 自定义用户控件

     此处为转载文章,用于记录自我学习过程,原文链接地址http://blog.csdn.net/xiongxuanwen/article/details/2605109 

    上篇:控件制作
     
    本例是制作一个简单的自定义控件,然后用一个简单的测试程序,对于初学者来说,本例子比较简单,只能起到抛石引玉的效果。
    我也是在学习当中,今后会将自己所学的逐步写出来和大家交流共享。
     
    第一步:新建一个控件库项目:myControl
     
    第二步:从工具箱里面拖动1个PictureBox、1个Button、6个Lable控件到用户界面上,布局如下:
           如上图,设置pictureBox的Name为picBox,背景为白色,Button的Name为btnOpen,另外靠左的三个Lable的Text属性分别为:文件名称,文件大小,文件尺寸,靠右的三个Lable的Name分别为:lblName, lblLength, lblSize.
     
    第三步:添加处理程序代码
    在btnOpen的Click事件写入代码,打开一个打开文件对话框,选择一个图形文件,打开并将它显示在picBox上。
     
    复制代码
    private void btnOpen_Click(object sender, EventArgs e)
    {
    OpenFileDialog ofdPic = new OpenFileDialog();
    ofdPic.Filter = "JPG(*.JPG;*.JPEG);gif文件(*.GIF)|*.jpg;*.jpeg;*.gif";
    ofdPic.FilterIndex = 1;
    ofdPic.RestoreDirectory = true;
    ofdPic.FileName = "";
    if (ofdPic.ShowDialog() == DialogResult.OK)
    {
    string sPicPaht = ofdPic.FileName.ToString();
    FileInfo fiPicInfo = new FileInfo(sPicPaht);
    long lPicLong = fiPicInfo.Length / 1024;
    string sPicName = fiPicInfo.Name;
    string sPicDirectory = fiPicInfo.Directory.ToString();
    string sPicDirectoryPath = fiPicInfo.DirectoryName;
    Bitmap bmPic = new Bitmap(sPicPaht);
    if (lPicLong > 400)
    {
    MessageBox.Show("此文件大小為" + lPicLong + "K;已超過最大限制的K范圍!");
    }
    else
    {
    Point ptLoction = new Point(bmPic.Size);
    if (ptLoction.X > picBox.Size.Width || ptLoction.Y > picBox.Size.Height)
    {
    picBox.SizeMode = PictureBoxSizeMode.Zoom;
    }
    else
    {
    picBox.SizeMode = PictureBoxSizeMode.CenterImage;
    }
    }
    picBox.LoadAsync(sPicPaht);
    lblName.Text = sPicName;
    lblLength.Text = lPicLong.ToString() + " KB";
    lblSize.Text = bmPic.Size.Width.ToString() + "×" + bmPic.Size.Height.ToString();
    }
    }
    复制代码
     
    第四步:测试控件
    按F5启动调试,弹出如下窗体:
    单击“打开”按钮,弹出打开文件对话框:
    选择一张图片,单击“打开”,可以看到在picBox上显示了打开的图片:
    第五步:查看成生的控件文件,到该项目文件目录下的bin->debug中可找到。
     
    下篇:控件测试
    第一步:新建一个C# Windows 应用程序,名为TestMyButton.
     
    第二步:增加自定义的用户控件
    右键单击工具箱中任意一个控件,弹出右键菜单如下:
    单击“选择项”,弹出如下对话框:
    单击“浏览”,弹出打开对话框:
    选中控件文件 mybutton.dll ,单击“打开”按钮,回到自定义工具箱,系统会默认把你刚才选中的控件打上 勾。
    返回vs编辑器,可看到工具箱中多出了一个UserControl:
     
    第三步:拖动1个自定义的控件到测试窗口
    第四步 测试程序
    单击“打开”按钮:
    选择一个图片,打开,显示该图:
    测试成功
    展开全文
  • labview自定义控件

    千次阅读 2018-06-01 09:53:12
    创建自定义输入控件、显示控件自定义类型»目录LabVIEW 2011帮助版本日期:June 2011产品编号:371361H-0118»查看产品信息下载帮助(仅限Windows)自定义输入控件和显示控件是对现有前面板对象集的扩展。...

    创建自定义输入控件、显示控件和自定义类型

    LabVIEW 2011帮助

    版本日期:June 2011

    产品编号:371361H-0118

    »查看产品信息
    下载帮助
    (仅限Windows)

    自定义输入控件和显示控件是对现有前面板对象集的扩展。用户可创建外观与内置LabVIEW输入控件及显示控件不同的自定义用户界面组件。将这种自定义输入控件或显示控件保存在某个目录或LLB中,就可以在其它前面板上使用该自定义控件。还可为自定义输入控件或显示控件创建图标并添加到控件选板。创建自定义控件前,请参考说明与建议

    自定义类型和严格自定义类型用于将所有自定义输入控件或显示控件实例与已保存的自定义输入控件或显示控件文件相连接。编辑已保存的自定义输入控件或显示控件文件可修改自定义输入控件或显示控件实例,以便在如干个VI中使用相同的自定义输入控件或显示控件。

    注:  另有XControl用于在LabVIEW中设计和创建复杂的输入控件和显示控件。与自定义控件不同,XControl具有由后台运行的VI所确定的动态运行时和编辑时行为。只有LabVIEW专业版开发系统中才有创建和修改XControl的功能。如VI包含XControl,可在所有LabVIEW版本上运行该VI。

    控件编辑器窗口

    控件编辑器窗口用于控件的自定义并为LabVIEW类定义私有数据控件。例如,改变控件的大小、颜色,控件中各元素的相对位置,向控件导入图像等。

    可通过以下方式打开控件编辑器窗口:

    • 右键单击前面板上的输入控件或显示控件,从快捷菜单中选择高级»自定义
    • 用定位工具选中前面板上的某个输入控件或显示控件后,选择编辑»自定义控件
    • 打开新建对话框。
    • 右键单击一个已有的控件或控件模板并选择打开
    • 项目浏览器窗口中右键单击我的电脑,从快捷菜单中选择新建»控件
    • 创建LabVIEW类并单击该私有数据控件。
      注:  对类私有数据控件进行定义时,控件编辑器窗口将打开并自动在程序框图上显示类私有数据的簇。同时,LabVIEW将控件编辑器窗口的下拉列表控件设置为默认的类私有数据,用户无法改动。
    • 在程序框图上右键单击自定义类型或严格自定义类型的实例,从快捷菜单中选择打开自定义类型

    虽然控件编辑器窗口在外观上与前面板十分相像,但其功能仅限于自定义单个的输入控件或显示控件。对于LabVIEW类,该控件必须为一个簇。控件编辑器窗口没有相应的程序框图且无法运行。

    控件编辑器窗口一次只能包含一个输入控件或显示控件。但是,控件编辑器窗口可对含有其他输入控件或显示控件的数组控件或簇控件进行自定义。数组或簇本身就是一个控件。当把输入控件或显示控件从数组或簇中移入或移出时,控件编辑器窗口的工具栏上将出现无效控件按钮。单击无效控件按钮,错误列表窗口将显示发生此错误的解释。

    控件编辑器窗口的工具栏用于提示用户当前处于编辑模式还是自定义模式。单击该按钮在两种模式之间切换。也可通过选择操作»切换至自定义模式操作»切换至编辑模式事件操作模式间的转换。控件编辑器窗口以编辑模式打开。

    与在前面板的编辑模式下的操作相同,控件编辑器的编辑模式可改变控件的大小及颜色,或在控件的快捷菜单中调整相应选项。

    自定义模式可通过改变控件的各个部件实现控件的大幅改动。

    自定义模式快捷菜单

    在自定义模式下,控件中每个部件的快捷菜单将取代整个控件的快捷菜单。不同的部件有不同的快捷菜单。快捷菜单可执行以下操作:

    • 自定义外观部件,例如,将修饰选板上的对象添加到自定义输入控件或显示控件。
    • 自定义文本部件,例如,名称标签。
    • 自定义作为部件使用的输入控件或显示控件,例如,滑动杆控件的数字显示的数值控件。数值控件还可作为旋钮、仪表和图表的数字显示。有些控件则更为复杂。例如,图表使用一个树形控件作为其光标的显示部件。

    自定义输入控件或显示控件的各个部件

    输入控件或显示控件的独立部件

    所有的输入控件和显示控件都由小型的部件组成。例如,下图显示了滑动杆控件的各个部件。

    控件编辑器窗口一旦切换到自定义模式,控件的各个部件即成为各自独立的部件。对每个部件进行的修改不会对其他部件造成影响。自定义模式显示了控件的所有部件,包括在编辑模式中隐藏的任何部件,如名称标签或数值控件上的基数。由于控件的各个部件相互脱离,因此在自定义模式下无法对控件的值进行操作或修改。

    在自定义模式下,可用定位工具选中控件的两个或更多个部件,使用对齐对象分布对象及工具栏上的重新排序下拉菜单将各个部件重新排列。

    控件部件窗口

    选择窗口»显示部件窗口可打开控件部件窗口。控件部件窗口用于调整控件中各个部件的大小并为各部件定位。控件部件窗口可识别出控件的各个部件,显示各个部件的确切位置并以像素为单位显示部件的大小。

    控件部件窗口的当前部件部分表示在控件编辑器窗口中所选部件的图形及名称。单击当前部件显示区可选择和显示控件中任意部件。单击当前部件显示框的向上或向下箭头,可滚动显示控件的所有部件。

    在控件编辑器窗口中移动部件的位置或调整部件大小时,LabVIEW也将在控件部件窗口的当前部件控件部件的位置与尺寸中改变相应部件的位置和大小。要实现上述操作,也可直接在部件位置和尺寸部分输入部件的位置和尺寸的值,这在令两个部件具有完全相同的大小且互相对齐时尤为有用。在部件位置和尺寸部分输入部件的位置和尺寸的值后,按下回车键或单击鼠标左键即可令修改生效。

    向自定义输入控件和显示控件添加外观部件

    可使用控件编辑器窗口在编辑模式或自定义模式下向自定义控件添加图形、文本或修饰。如从剪贴板粘贴一个图形或一段文本,或用标签工具创建一个标签,或从修饰选板选择一个修饰,则该操作对象便成为控件的一个新的修饰部件,并同控件一起出现在前面板上。在控件编辑器窗口中,可移动部件位置、调整部件大小、改变层叠次序或替换新的修饰部件。在前面板上使用自定义控件时,可对任何添加到控件上的修饰部件进行大小调整。但不可改变这些添加的修饰部件的位置。

    自定义外观部件的模式快捷菜单项

    外观部件可在不同场合显示单个或多个各自独立的图形。要自定义外观部件,应把控件编辑器窗口切换至自定义模式并右键单击需自定义的外观部件。外观部件快捷菜单中出现的选项取决于该外观部件的类型。

    具有单个图形的外观部件

    具有单个图形的外观部件的快捷菜单包含以下选项:

    • 复制到剪贴板—-将部件的图形副本放置到剪贴板上。将一个图形复制到剪贴板后,右键单击一个部件并从快捷菜单中选择从剪贴板导入图片,将图形导入部件。

      如需在自定义外观部件时用到简单的图形,可从其他输入控件或显示控件的内置部件复制,这样就无需在图形应用程序中再行创建。例如,如需一个简单的矩形的图形,可右键单击该外形为矩形的部件的衬底并从快捷菜单中选择复制到剪贴板。从内置部件或修饰中导入的图形比在图形应用程序中创建的图形更易调整大小。例如,为一个在图形应用程序中绘制的矩形调整大小时,矩形将整体扩展,面积增大的同时边框变宽。而为一个从内置控件的部件复制而来的矩形调整大小时,矩形的边框将保持其原有宽度。  

      从内置控件复制而来的部件在彩色或黑白显示器上显示出的外观相似。此外,使用上色工具可为由内置部件和修饰复制而来的图形添加色彩。由于颜色已在图形的定义中规定,故从其他来源导入的图形的颜色无法修改。
    • 从剪贴板导入图片—用剪贴板上的图形替换外观部件当前使用的图形。例如,可为一个布尔开关的打开或关闭状态导入图形。如剪贴板不含有图形,则从剪贴板导入图片选项不可用。
    • 以相同大小从剪贴板导入—用剪贴板上的图形替换外观部件当前使用的图形,缩放导入的图形使之适合部件的大小。如剪贴板不含有图形,则以相同大小从剪贴板导入选项不可用。
    • 从文件导入—从文件对话框中选择图形以替换外观部件当前使用的图形。
    • 以相同大小从文件导入—从文件对话框中选择图形以替换外观部件当前使用的图形,缩放导入的图形使之适合部件的大小。
    • 恢复—不改变部件的位置将其恢复到原来的外观。如在前面板上打开某个控件的控件编辑器窗口并对其部件进行改动,则从其快捷菜单中选择恢复将恢复该部件在前面板上的外观。如在控件编辑器窗口中打开自定义的控件,则恢复选项不可用。
    • 原始大小—将部件的图形恢复至其原始大小,便于从其他应用程序中导入图形并调整图形大小。有些从其他应用程序导入的图形经大小调整后显示效果不如其原始图形。此时需要将导入的图形恢复至其原始大小以提高其显示质量。如不导入图形,则原始大小选项不可用。
    注:  也可以剪贴板上的图像替换修饰部件所使用的图形,即选中一个修饰部件,再选择编辑»粘贴。如需以一个文件中的图像替换修饰部件所使用的图形,可右键单击该修饰部件,从快捷菜单中选择从文件导入

    具有多个相关图形的外观部件

    有些外观部件具有多个相关图形以表示不同的状态。这些不同的图形大小、颜色相同。对外观部件的当前图形进行移动或调整大小时,该部件的其他图形也将随之移动或大小成比改变。例如,布尔开关有四个不同的图形。第一个图形表示状态为FALSE。第二个图形表示状态为TRUE。第三个图形表示释放时切换的状态,即从TRUE到FALSE的过渡状态。第四个图形表示“释放时触发”的状态,即从FALSE到TRUE的过渡状态。当布尔控件处于“释放时切换”或“释放时触发”的状态时,布尔控件的值将在鼠标按钮被释放时才改变。在单击鼠标按钮和释放鼠标按钮两个动作之间,布尔控件将显示作为过渡状态的第三或第四个图形。

    对于具有多个相关图形的外观部件,其快捷菜单不仅包含了具有单个图形的外观部件的所有菜单选项,还包含了图片项的选项。从快捷菜单中选择图片项可显示一个外观部件名下所有的图形。当前图形外部围有深色边框。导入图形仅改变当前图形。如需为其他图形导入图形,应右键单击部件,从快捷菜单中选择图片项,从中选择需导入的新图形后将其导入。

    具有多个独立图形的外观部件

    对于具有多个图形的外观部件,这些图形的颜色和大小可不尽相同。例如,滑动杆控件通过两个大小不同的图形表示多值滑动杆上处于活动状态的滑块。对于具有多个独立图形的外观部件,其快捷菜单不仅包含了单个图形或多个相关图形的外观部件的所有菜单项,还包含了独立大小这一菜单项。从外观部件的快捷菜单中选择独立大小并勾选旁边的复选框可在不改变该外观部件其他图形的前提下,移动其中每个图形的位置并调整图形大小。

    文本部件

    文本部件是一个带有文本的图形,如标签。文本部件的快捷菜单包含了具有单个图形的外观部件的所有菜单选项,以及在编辑模式下前面板中所有可用的文本元素。控件部件窗口仅显示文本部件的背景图形而不显示文本。背景图形可自定义,但文本无法自定义。

    布尔控件的编辑模式

    与其他类型控件只可在控件编辑器窗口为自定义模式下导入图形不同,布尔输入控件及显示控件可在控件编辑器窗口的编辑模式下导入图形。当控件编辑器窗口处于编辑模式时,右键单击布尔输入控件或显示控件,则弹出的快捷菜单将包含所有编辑模式下前面板上可用的布尔控件,以及从剪贴板导入图片菜单项。

    连接自定义输入控件和显示控件并保存到一个自定义输入控件或显示控件文件

    在VI中使用自定义输入控件或显示控件后,该VI中自定义控件的实例与所保存的控件间的连接将不复存在。自定义输入控件或显示控件的每个实例是一个单独、独立的副本。因此,改变自定义控件并不影响正在使用该自定义控件的VI。如需使自定义输入控件或显示控件的实例与自定义输入控件或显示控件文件相连接,可将该自定义输入控件或显示控件另存为一个自定义类型或严格自定义类型。一个自定义类型或严格自定义类型的所有实例与其原始文件相连。

    将自定义输入控件或显示控件另存为一个自定义类型或严格自定义类型后,对该自定义类型或严格自定义类型所作的任何数据类型改动将对所有使用这些自定义类型或严格自定义类型的VI实例造成影响。与此同时,对严格自定义类型所作的外观改动也将影响前面板上该严格自定义类型的所有实例。

    自定义类型和严格自定义类型

    自定义类型和严格自定义类型可将所有自定义输入控件或显示控件的实例连接到已保存的自定义输入控件或显示控件文件。编辑已保存的自定义输入控件或显示控件文件可修改所有自定义输入控件或显示控件实例,以便在如干个VI中使用相同的自定义输入控件或显示控件。

    自定义类型

    自定义类型为自定义输入控件或显示控件的每个实例指定了正确的数据类型。如自定义类型的数据类型发生改变,则该自定义类型的所有实例将自动更新。换言之,在使用了该自定义类型的每个VI中,各实例的数据类型将改变。然而,由于自定义类型仅规定了数据类型,仅有数据类型那部分的值被更新。例如,数值控件中的数据范围便不是数据类型的一部分。因此,数值控件的自定义类型并不定义该自定义类型实例的数据范围。同时,由于下拉列表控件各选项的名称没有定义其数据类型,因此在自定义类型中对下拉列表控件中各选项的名称进行改动将不会改变自定义类型实例中各项的名称。如在一个枚举型控件的自定义类型中改变其选项名称,由于选项名称也是枚举型控件数据类型的一部分,因此其实例将发生更新。自定义类型实例可拥有其唯一的标签、描述、默认值、大小、颜色,或设定其风格为输入控件或显示控件,如滑动杆或旋钮。

    如改变一个自定义类型的数据类型,LabVIEW将尽可能把该自定义类型实例的原有默认值转换为新的数据类型。如数据类型被改为一个不兼容的类型,如数值控件被替换为字符控件,则LabVIEW将无法保留实例的默认值。如自定义类型的数据类型被改为其先前所无法兼容的数据类型,LabVIEW将把该自定义类型的默认值设置为用户在.ctl文件中指定的值。如用户未指定默认值,LabVIEW将使用相应数据类型的默认值。例如,如自定义类型从数值改为字符串,则LabVIEW将把与先前数值型数据类型相关的所有默认值替换为空字符串。

    严格自定义类型

    严格自定义类型将把实例除标签、描述和默认值外每个方面强制设置为与严格自定义类型相同。对于自定义类型,严格自定义类型的数据类型将在任何使用该严格自定义类型的场合下保持不变。严格自定义类型也对其他值进行了定义,如对数值控件及下拉列表控件中控件名称的范围检查。严格自定义类型可使用的VI服务器属性仅限于对控件外观产生影响的属性,包括可见、禁用、键选中、闪烁、位置和边界。

    将实例与严格自定义类型移除连接,可阻止自定义类型实例进行自动更新。

    创建和编辑自定义类型和严格自定义类型

    可在前面板和程序框图上创建和编辑自定义类型或严格自定义类型。控件编辑器窗口和自定义控件的各种技巧也适用于创建和编辑自定义类型。

    阻止自定义类型实例的自动更新

    右键单击实例,取消快捷菜单中勾选的从自定义类型自动更新选项,可阻止当自定义类型的数据类型改变时,自定义类型的某个实例进行自动更新。取消勾选从自定义类型自动更新可阻止实例在自定义类型的数据类型发生改变时进行自动更新,但仍保留实例与自定义类型的连接。如需断开实例与自定义类型的连接,可右键单击实例,从快捷菜单中选择断开连接自定义类型

    注:  将实例与严格自定义类型移除连接,可阻止自定义类型实例进行自动更新。

    如禁用自定义类型实例的自动更新并改变实例的数据类型,则该实例将模糊显示且运行按钮显示为断开。如需启用该实例,可右键单击该实例,从快捷菜单中选择从自定义类型更新断开连接自定义类型。选择从自定义类型更新将把实例的数据类型改为自定义类型的数据类型。断开连接自定义类型将使实例与自定义类型间永久地移除连接

    当自定义类型的数据类型被更改后,打开含有该自定义类型实例的VI,所有自动更新被禁用的实例将模糊显示。同时,运行按钮也以断开显示。如需启用该实例,可右键单击该实例,从快捷菜单中选择从自定义类型更新断开连接自定义类型

    移除实例与自定义类型或严格自定义类型的连接

    右键单击实例,从快捷菜单中选择断开连接自定义类型,可永久断开自定义类型或严格自定义类型与其实例间的连接。断开与自定义类型或严格自定义类型的连接将取消实例使用数据类型的限制,令实例成为一个输入控件或显示控件。

    不可用的自定义类型和严格自定义类型

    对于每个自定义类型或严格自定义类型实例,含有该实例的VI将与保存该自定义类型或自定义类型文件保持连接。如VI含有需要运行的自定义类型或严格自定义类型实例,则VI必须具备含有该自定义类型或严格自定义类型的文件。如VI已打开而LabVIEW无法找到该VI所需的自定义类型或严格自定义类型,LabVIEW将禁用该VI中的自定义类型或严格自定义类型实例,运行按钮也将显示为断开。如需VI运行,应找到并打开正确的自定义类型或严格自定义类型。也可右键单击被禁用的实例,从快捷菜单中选择断开连接自定义类型以永久断开实例与自定义类型或严格自定义类型的连接。

    使用自定义类型和严格自定义类型

    自定义类型和严格自定义类型可以像任何自定义输入控件或显示控件一样,放置于前面板或程序框图上。右键单击自定义类型或严格自定义类型实例,其快捷菜单包括各种自定义类型的选项。如需从前面板或程序框图打开自定义类型或严格自定义类型,可右键单击实例,从快捷菜单中选择打开自定义类型

    程序框图上自定义类型或严格自定义类型的左上角的符号表示当前的类型实例。将鼠标移至该符号,提示框将显示自定义类型或严格自定义类型的名称。修改自定义类型将对程序框图上的实例造成影响,即程序框图上的实例根据前面板上所作修改相应发生改变。但是,如改变一个严格自定义类型,放置在程序框图上的常量显示为严格类型,只有数据类型改变,常量才会相应改变。例如,如更新一个严格自定义类型下拉列表控件中的字符串值,LabVIEW不会更新放置在程序框图上该严格自定义类型常量,因为字符串值不是下拉列表控件的数据类型。

    使用簇自定义类型和簇严格自定义类型

    如将簇自定义类型或簇严格自定义类型放置于前面板,可用程序框图上的按名称捆绑函数及按名称解除捆绑函数访问簇的元素。与捆绑函数和解除捆绑函数按照簇顺序引用簇元素不同,“按名称捆绑”函数和“按名称解除捆绑”函数按照名称引用元素。因此,元素的重新排序、向簇自定义类型或簇严格自定义类型添加新元素均不会使VI断开。

    对于簇自定义类型或簇严格自定义类型,与“按名称捆绑”函数和“按名称解除捆绑”函数连接后,如其中某个元素被删除,则该丢失元素的引用便无效,从而必须对程序框图进行修改。“按名称捆绑”函数和“按名称解除捆绑”函数中的无效名称显示为黑色。单击“按名称捆绑”函数和“按名称解除捆绑”函数将打开有效名称的列表,可视需选择其中的名称。

    对簇自定义类型或簇严格自定义类型中的控件创建引用时,LabVIEW使用簇的顺序来决定引用指向簇中的哪个控件。如从簇自定义类型或簇严格自定义类型中删除一个控件,引用指向的控件可能会产生错误。从簇自定义类型或簇严格自定义类型中删除一个控件时,确保各个引用仍指向原簇控件。

    展开全文
  • Android自定义控件的三种实现方式

    万次阅读 多人点赞 2017-10-19 16:25:14
    Android 自定义控件三种实现方法为组合原生控件,自己绘制和继承原生控件. 1.组合原生控件 将自己需要的控件组合起来变成一个新控件,如下制作常见的app页面头部.  新建一个Android项目,创建一个头部布局view_top....
  • 自定义控件其实很简单1

    千次阅读 2018-08-20 06:43:55
    自定义View,很多初学Android的童鞋听到这么一句话绝逼是一脸膜拜!因为在很多初学者眼里,能够自己去画一个View绝逼是一件很屌很Cool的事!但是,同样而言,自定义View对初学者来说却往往可望而不可及,可望是因为...
  • 自定义控件

    2019-01-12 09:01:40
    o# 自定义控件 # Day01 系统控件回顾 文本控件 TextView和EditText 图片控件 ImageView 按钮控件 Button和ImageButton 进度条 ProgressBar 单选按钮 RadioButton和RadioGroup 复选按钮 CheckBox 状态开关按钮...
  • Android 自定义控件之组合控件

    万次阅读 2018-04-18 20:46:39
    一、前言 最近做一个项目又一次用到类似像微信... 这回使用的Android的自定义控件中的组合控件。二、自定义组合控件原理 项目中经常会遇见很多相似或者相同的布局,比如APP的标题栏,通过将这些布局抽取出来,放...
  • C#自定义控件的创建

    万次阅读 2019-06-14 14:19:51
    本人在开发自定义控件时走了一些弯路,写下此篇,希望能够给有需要的朋友一些帮助,也借此加深自己的印象。 1.创建自定义控件 选择【经典桌面】——【窗体控件库】 2.添加控件,组合成一个新的控件 自定...
  • 如何自定义控件

    2018-06-21 12:08:31
    【WinForm】创建自定义控件虽然VS为我们提供了很多控件可以使用,但有时候这些控件仍然不能满足我们的要求,比如我们要对部分控件进行一些个性化的定制,例如美化控件,这时候就需要自己绘制控件,或是在原有控件的...
  • Android自定义控件三部曲文章索引

    万次阅读 多人点赞 2019-09-17 19:53:00
    前言:在我从C++转到Android时,就被Android里炫彩斑斓的自定义控件深深折服,想知道如果想利用C++实现这些功能,那是相当困难的。从那时候起,我就想,等我学会了自定义控件,一定要写一篇系列出来,方便后来者能更...
  • Qt编写自定义控件大全

    万次阅读 多人点赞 2019-07-05 10:03:48
    设计师designer完整源码(仅限Qt4):https://pan.baidu.com/s/1t9uKOgi7PW34Kdj7rgTlrA 设计师designer可执行文件:...自定义控件Qt4封装版本:https://pan.baidu.com/s/1JnpCwIW5sY9VtViqHSCi1g ...
  • 我的新书《Android自定义控件入门与实战》出版啦

    万次阅读 多人点赞 2019-09-12 14:17:42
    【Android自定义控件入门与实战】勘误:https://blog.csdn.net/harvic880925/article/details/89459263 【本书资源及第一章、第十一章PDF下载地址】: https://github.com/harvic/AndroidCusto...
  • 自定义控件其实很简单1/12

    万次阅读 多人点赞 2015-01-13 16:37:08
    自定义View,很多初学Android的童鞋听到这么一句话绝逼是一脸膜拜!因为在很多初学者眼里,能够自己去画一个View绝逼是一件很屌很Cool的事!但是,同样而言,自定义View对初学者来说却往往可望而不可及,可望是因为...
  • 1.开发环境 Qt版本:Qt 4.8.7 编译器:MinGw 系统:Windows 2.创建Qt4自定义控件 ...此时编译出来Release版本的自定义控件放进Designer目录下仅能在Designer中拖动,在使用该控件的工程中编译将会报错,所...
  • Android自定义控件——自定义属性

    万次阅读 热门讨论 2014-09-18 13:03:52
    我们在自定义android组件的时候,除了用Java构建出组件的样子外,有时候还需要去申明一些“属性”提供给项目使用,那么什么是组件的属性呢? 例如在清单文件中,创建一个TextView的时候,这是需要制定TextView的...
  • Qt编写自定义控件20-自定义饼图

    千次阅读 2019-06-03 23:32:25
    为了逐步移除对QChart的依赖(主要是因为QChart真的太垃圾了,是所有Qt的模块中源码最烂的一个,看过源码的人没有一个不吐槽,不仅不支持10W级别的数据量曲线展示,居然一个饼图控件,文字部分的展示还用QLabel来...
  • 本篇博客的目的是简单介绍:创建一个用QLabel类来显示图片的自定义控件的编写。在写自定义控件的过程中遇到了很多的难题,但都慢慢解决了,本人对Qt自定义控件的认识还不深刻,做的不对的地方,还请大家指出,我会...
  • Qt添加自定义控件

    万次阅读 热门讨论 2019-07-25 23:44:55
    本文详细介绍在Windows 10和Ubuntu 14.04系统下,使用Qt Creator 4.9.0创建自定义控件的过程,并在项目中使用
1 2 3 4 5 ... 20
收藏数 339,396
精华内容 135,758
关键字:

自定义控件