>

Winform itch에 버튼, 2 개의 레이블 및 이미지가있는 패널이 있습니다. 이제 진행률 표시 줄로 패널 배경의 색상을 아래쪽에서 위쪽으로 점차 변경하고 싶습니다. 두 번째 패널이있는 구성 요소가있는 패널을 사용하여 첫 번째 패널 위에 있지만 구성 요소 뒤에 시도한 다음 점차 두 번째 패널의 높이를 확장했습니다. 그러나 구성 요소의 배경색은 첫 번째 패널의 색을 상기시킵니다. 구성 요소의 배경색을 투명하게 설정하려고했습니다.

이 효과를 달성하기위한 제안이있는 사람이 있습니까? 패널과 함께있을 필요는 없습니다. 구성 요소가 해당 영역의 맨 위에 있고 배경색이 변하기 만하면됩니다.

미리 감사합니다

  • 답변 # 1

    Windows Forms 응용 프로그램을 사용하면 원하는 효과를 얻을 수 있습니다. 거기에 당신을 데려 갈 많은 옵션이 있지만, 나는 Paint 를 다룰 것입니다  사용자에게 사각형을 페인트하여 진행 상황을 사용자에게 표시 할 수있는 이벤트 옵션. 이 경로를 효과적으로 보여주는 두 가지 방법이 있습니다. 그 중 하나는 Timer 를 사용한 단순한 접근 방식입니다  다른 하나는보다 심층적 인 접근 방법이지만 백그라운드 스레드에서 진행률을 표시하는 데 더 적합합니다.

    <시간> 와이즈 비즈  옵션 Timer 사용  최소한의 코드로이 효과를 재현 할 수 있습니다. 당신은 단순히 Timer 가 필요합니다 , Panel  그리고 Timer  진행 상황을 추적합니다. Wyzwyz에서  우리는 float 에 타이머를 시작  진행률을 높이고 패널을 무효화하고 FormLoad 에서  우리는 우리의 커스텀 진보를 그린다 :

    TimerTick
    
    

    알다시피,이 방법의 코드는 매우 간단하고 쉽게 설명 할 수 있습니다.

    <시간> 이벤트 옵션

    백그라운드 스레드에 물건을로드 할 때 PanelPaint 와 같은 GUI 요소를 업데이트 할 때 상황이 조금 더 복잡해질 수 있습니다 . 이 경우 나는 private float progress = 0f; private void Form1_Load(object sender, EventArgs e) => timer1.Start(); private void timer1_Tick(object sender, EventArgs e) { progress += 0.01f; if (progress >= 1.0f) progress = 0f; panel1.Invalidate(); } private void panel1_Paint(object sender, PaintEventArgs e) { e.Graphics.FillRectangle(Brushes.Green, new Rectangle(0, 0, panel1.Width, (int)(panel1.Height * progress))); } 를 사용하는 것을 선호합니다   Panel 를 발생시키지 않고 GUI 요소를 업데이트하는 양식에서 이벤트를 발생시키는 방법 에스. 그러나이 특정 예제에서는 상황이 비교적 간단하고 위와 같은 방식으로 작동하지만 더 많은 코드가 사용됩니다. 우리 SynchronizationContext 가 있다고  모든 백그라운드 로딩을 ​​처리하며 모두 별도의 스레드에서 발생합니다. 이 경우 양식에 가입 한 커스텀 이벤트와 CrossThreadException 가 있습니다.  폼이 GUI를 업데이트 할 수 있도록 이벤트를 발생시킵니다.

    class
    
    

    이제 로딩 클래스가 빌드되고 객체와 그 재미있는 재즈가 모두 생성되었으므로 타이머와 동일한 작업을 수행하기 위해 폼 코드에 추가 할 수 있습니다. 이 방법으로 우리는 SyncrhonizationContext 를 구독합니다  이벤트와 동일한 프로세스를 따릅니다.

    public class DataLoader {
        #region Fields
        private bool loading = true;
        private Thread loadingThread;
        private SynchronizationContext loadingContext;
        #endregion
        #region Properties
        public float Progress { get; private set; } = 0f;
        #endregion
        #region Events
        public event EventHandler ObjectLoaded;
        private void OnObjectLoaded() => loadingContext.Post(new SendOrPostCallback(PostObjectLoaded), new EventArgs());
        private void PostObjectLoaded(object data) => ObjectLoaded?.Invoke(this, (EventArgs)data);
        #endregion
        #region Constructor(s)
        public DataLoader() {
            if (SynchronizationContext.Current != null)
                loadingContext = SynchronizationContext.Current;
            else
                loadingContext = new SynchronizationContext();
            loadingThread = new Thread(new ThreadStart(LoadData));
            loadingThread.IsBackground = true;
            loadingThread.Start();
        }
        #endregion
    
        #region Private Methods
        private void LoadData() {
            while (loading) {
                // Do some cool stuff to load data.
                CoolStuff();
                // Increment progress.
                Progress += 0.01f;
                if (Progress >= 1.0f)
                    loading = false;
                // Now this object is loaded, raise event for subscribers.
                OnObjectLoaded();
            }
        }
        private void CoolStuff() {
            // Do cool loading stuff.
        }
        #endregion
    }
    
    

    <시간> 바닥에서 사각형 채우기

    아래에서 직사각형을 채우려면 위치와 높이를 동시에 조정해야합니다.

    ObjectLoaded
    
    

    오른쪽에서 왼쪽으로의 동일한 개념과 왼쪽에서 오른쪽으로의 원래 예제를 따를 수 있습니다.

    private DataLoader loader;
    private void Form1_Load(object sender, EventArgs e) {
        loader = new DataLoader();
        loader.ObjectLoaded += loader_ObjectLoaded;
    }
    private void loader_ObjectLoaded(object sender, EventArgs e) => panel1.Invalidate();
    private void panel1_Paint(object sender, PaintEventArgs e) {
        e.Graphics.FillRectangle(Brushes.Green, new Rectangle(0, 0, panel1.Width, (int)(panel1.Height * loader.Progress)));
    }
    
    

    스모크 로더와 같은 연기 및 거울 모양의 외관을 얻기 위해 특정 지점에서 시작하는 기술도 있지만 필요한 경우 알아볼 수 있도록 남겨 두겠습니다.

    또한 당신의 int height = panel1.Height * progress; Rectangle bounds = new Rectangle(0, panel1.height - height, panel1.Width, height); e.Graphics.FillRectangle(Brushes.Green, bounds) 를 기억하십시오   width = panel1.width * progress; Rectangle bounds = new Rectangle(panel1.Width - width, 0, width, panel1.Height); 이어야한다   Progress 사이의 가치  그리고 float ;그렇지 않으면 0 로 나누어야합니다  위를 수행 할 때. 진행이 1 사이에있는 경우  그리고 100  그냥 0 를 곱하십시오  표시 목적으로. 나는 항상 1 사이에 진행을 유지하는 것이 더 쉽다는 것을 알았습니다  그리고 100  계산에 많이 사용하고 한 번만 표시하기 때문에 사용합니다.

    <시간> 100 %로 진행 중지

    의견에서 나는 당신이 내 예제에서 진행 증분을 남겼으며 0 에 의해 증가한다고 생각합니다. . 이것은 올바른 방법이 아니며 단지 예일뿐입니다.

    전통적으로 총 작업 수 (또는 파일의 경우 총 크기)를 파악하고 완료된 양을 해당 총 수로 나누어 진행 상황을 파악할 수 있습니다. 아래는 처리 할 객체 목록이있는 기본 예입니다.

    1
    
    

    이 특별한 경우에, 당신은 0.01f 에 대한 호출을 제거합니다  Wyzwyz에서  중복 이벤트 발생을 방지하기 위해 메소드의 while 루프.

    <시간>

    사용 된 유형 중 하나라도 익숙하지 않은 경우 MSDN 설명서를 자유롭게보십시오. 아래에 가장 흔하지 않은 부분이 포함되어 있습니다. 관심있는 항목이 목록에 없으면 사과드립니다. 언제든지 댓글을 달고 추가 할 수 있습니다.

    동기화 컨텍스트

    나사

    보내기 및 게시

    또한 미래 독자들에게 발생할 수있는 질문에 대답하기 위해;내가 private List<object> ObjectsToLoad = new List<object>(); private void DoCoolStuff() { int objectsLoaded = 0; foreach (object o in ObjectsToLoad) { // Process the object. Progress = (float)++objectsLoaded / (float)ObjectsToLoad.Count;; OnObjectLoaded(); } } 를 사용한 이유   OnObjectLoaded 대신  이 경우 백그라운드 스레드가 실제로 GUI가 수행 해야하는 작업에 관심이 있다고 믿지 않았기 때문에 GUI에 알려야했습니다. 와이즈 비즈  스레드가 처리를 계속하도록 지시하면서 Load  스레드가 loadingContext.Post 를 기다리도록 지시합니다.  GUI 스레드에서. 와이즈 비즈  GUI가 백그라운드 스레드에서 전송 한 데이터를 조작 한 다음 다시 보내거나 백그라운드 스레드에서 무언가를 업데이트해야 할 때 가장 적합합니다.

    향후의 노력에 당신에게 행운을 빕니다!

    loadingContext.Send

  • 이전 java - 429 aws-sdk를 사용하여 s3 객체에 대해 미리 서명 된 URL을 생성 할 때 요청이 너무 많습니다
  • 다음 python - 데이터 프레임 사전 데이터 프레임 이름 선택