整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          如何實(shí)現(xiàn)一個(gè)超絲滑的勾選框組件?

          Zag 和 PandaCSS 都是出自 chakra 團(tuán)隊(duì)之手,Zag 聚焦于處理組件的邏輯,而 PandaCSS 聚焦于通過 ts 來維護(hù)樣式,將兩者進(jìn)行搭配會(huì)有怎么樣的使用體驗(yàn)?zāi)兀窟@篇文章將繼續(xù)以 vuesax 中 checkbox 組件的樣式作為參考,結(jié)合 Zag 和 PandaCSS 進(jìn)行 vue3 版本的重構(gòu),實(shí)現(xiàn)一個(gè)超絲滑的勾選框組件。


          使用 Zag 實(shí)現(xiàn)核心邏輯

          Zag 中將 Checkbox 分為三個(gè)組成部分:

          • root:根元素,用于包裹內(nèi)部元素
          • control: 控制器
          • label: 標(biāo)簽內(nèi)容

          我們首先在 Zag Checkbox 文檔中復(fù)制 JSX 的實(shí)例代碼:

          import * as checkbox from "@zag-js/checkbox"
          import { normalizeProps, useMachine } from "@zag-js/vue"
          import { defineComponent, h, Fragment, computed } from "vue"
          
          export default defineComponent({
            name: "Checkbox",
            setup() {
              const [state, send] = useMachine(checkbox.machine({ id: "checkbox" }))
          
              const apiRef = computed(() =>
                checkbox.connect(state.value, send, normalizeProps),
              )
          
              return () => {
                const api = apiRef.value
                return (
                  <label {...api.rootProps}>
                    <span {...api.labelProps}>
                      Input is {api.isChecked ? "checked" : "unchecked"}
                    </span>
                    <div {...api.controlProps} />
                    <input {...api.hiddenInputProps} />
                  </label>
                )
              }
            },
          })

          這段代碼使用了 useMachine 函數(shù)創(chuàng)建了一個(gè)狀態(tài)機(jī),并且寫了一個(gè)無樣式的基礎(chǔ) checkbox 結(jié)構(gòu):

          接下來我們?yōu)?checkbox 組件補(bǔ)充樣式.

          實(shí)現(xiàn)打勾動(dòng)畫圖標(biāo)

          想要實(shí)現(xiàn)絲滑的勾選框效果,最直觀的是打勾的動(dòng)畫。這個(gè)效果可以通過 SVG 或者純 css 實(shí)現(xiàn),這里我使用的是 css 來實(shí)現(xiàn)的。:

          首先我們要想想如何實(shí)現(xiàn)一個(gè)勾勾的效果,??由一長一短兩個(gè)斜邊組成,那么我們只需要放置一個(gè)矩形,設(shè)置一定的旋轉(zhuǎn)角度,并設(shè)置其中的兩個(gè)邊框,就能實(shí)現(xiàn)一個(gè)??的形狀:

          代碼實(shí)現(xiàn)如下:


          import { defineComponent } from "vue";
          
          import { css, cx } from "@/styled-system/css";
          
          const IconCheck = defineComponent({
            props: {
              color: {
                type: String,
                default: css({ colorPalette: "gray" }),
              },
              size: {
                type: String,
                default: css({ colorPalette: "gray" }),
              },
              customCSS: {
                type: String,
              },
            },
            setup(props) {
              return () => (
                <i
                  class={cx(
                    css({
                      display: "flex",
                      alignItems: "center",
                      justifyContent: "center",
                    }),
                    props.customCSS,
                  )}
                >
                  <div
                    class={css({
                      position: "relative",
                      width: "80%",
                      height: "40%",
                      transform: "rotate(-45deg)",
                    })}
                  >
                    <div
                      class={css({
                        position: "absolute",
                        left: "0",
                        width: "full",
                        height: "full",
                        borderLeft: "2px solid white",
                        animation: "checkShort 0.15s",
                      })}
                    />
                    <div
                      class={css({
                        position: "absolute",
                        left: "0",
                        width: "full",
                        height: "full",
                        borderBottom: "2px solid white",
                        animation: "checkLong 0.5s",
                      })}
                    />
                  </div>
                </i>
              );
            },
          });
          
          export default IconCheck;

          上面這段代碼中,定義了一個(gè)矩形,寬高分別為最外層容器的 80% 和 40%,transform: "rotate(-45deg)", 則設(shè)置了矩形的旋轉(zhuǎn)角度,內(nèi)部放置兩個(gè)與矩形寬高一致的容器,分別設(shè)置 borderLeft 和 borderBottom ,這樣就組成了一長一短兩條線。

          這里之所以需要在內(nèi)部放兩個(gè)容器單獨(dú)設(shè)置邊框,而不是直接在矩形設(shè)置邊框,是為了更好的實(shí)現(xiàn)動(dòng)畫效果,長短邊分別設(shè)置了兩個(gè)持續(xù)時(shí)間不同的動(dòng)畫 checkShort 0.15s 和 checkLong 0.5s:

          checkShort: {
            "0%": {
              height:0,
            },
            "100%":{
              height: "full",
            }
          },
          checkLong: {
            "0%": {
              width: 0,
            },
            "30%":{
              width: 0,
            },
            "100%": {
              width: "full",
            }
          }

          短邊從最開始就執(zhí)行動(dòng)畫,持續(xù)時(shí)間為長邊動(dòng)畫的 30%,長邊則在 0-30% 時(shí)不執(zhí)行,30% 之后開始執(zhí)行,這樣就能實(shí)現(xiàn)短邊動(dòng)畫執(zhí)行完成后,長邊動(dòng)畫再執(zhí)行的效果。

          之所以不使用 animation-delay 去延遲執(zhí)行長邊動(dòng)畫,是因?yàn)檫@種方式會(huì)導(dǎo)致動(dòng)畫延遲執(zhí)行前,長邊會(huì)先展示出來,效果就不對了。如果要使用這種方式還得單獨(dú)做一些動(dòng)畫延遲前的隱藏處理,會(huì)比較麻煩:

          實(shí)現(xiàn) Hover 效果

          為了讓用戶更容易感知勾選框是可以交互的,我們?yōu)楣催x框增加未勾選和關(guān)狀態(tài)的 hover 效果。

          未勾選狀態(tài)

          未勾選狀態(tài)的 hover 效果,默認(rèn)只有灰色邊框,鼠標(biāo)懸浮后變?yōu)榛疑尘埃?/p>

          這里有個(gè)注意點(diǎn),我們鼠標(biāo)懸浮在勾選框的最外層,也可以觸發(fā)內(nèi)層的 hover 樣式,如果直接使用 hover 效果是沒法做到的,這樣只能鼠標(biāo)懸浮在邊框內(nèi)才能觸發(fā)。

          如果我們沒有使用任何樣式庫,實(shí)現(xiàn)這個(gè)效果可以通過維護(hù)一個(gè) 鼠標(biāo)是否 hover 的狀態(tài),并通過 onMouseEnter 和 onMouseLeave 來更新這個(gè)狀態(tài),再在內(nèi)層根據(jù)這個(gè)狀態(tài)動(dòng)態(tài)渲染樣式。

          但這里我們可以使用 pandaCSS 的 group 選擇器來實(shí)現(xiàn)。

          首先在勾選框最外層元素增加 group 類名:

          <label
            {...api.rootProps}
            class={[
              css({
                display: "flex",
                alignItems: "center",
                cursor: "pointer",
              }),
          +    "group",
            ]}
          >

          然后在內(nèi)層的 control 元素增加基礎(chǔ)樣式:

          <div
              {...api.controlProps}
              class={css({
                width: "24px",
                height: "24px",
                borderRadius: "8px",
                border: api.isChecked
                  ? "none"
                  : "token(colors.gray.200) solid 2px",
                transition: "all 0.3s",
                marginRight: "4px",
                flexShrink: "0",
                _groupHover: {
                  background: "gray.200",
                },
              })}
            >
            // ...
            </div>

          這里的 _groupHover 即為 group 選擇器,當(dāng)帶有 group 類名的元素觸發(fā) hover 時(shí),內(nèi)部的元素都可以使用 _groupHover 設(shè)置特定樣式。這樣我們就實(shí)現(xiàn)了前文圖中的效果。

          勾選狀態(tài)

          在勾選時(shí),會(huì)有一個(gè)藍(lán)色色塊放大漸出的效果,我們先來實(shí)現(xiàn)這個(gè)樣式。

          <Transition
            enterFromClass={css({
              transition: "all 0.2s",
              transform: "scale(0.5)",
              opacity: "0",
            })}
            enterToClass={css({
              transition: "all 0.2s",
              transform: "scale(1)",
              opacity: "1",
            })}
            leaveToClass={css({
              transition: "all 0.2s",
              transform: "scale(0.5)",
              opacity: "0",
            })}
          >
            {api.isChecked && (
              <div
                class={cx(
                  props.color,
                  css({
                    width: "full",
                    height: "full",
                    background: "colorPalette.600",
                    borderRadius: "inherit",
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                    transition: "all 0.3s",
                  }),
                )}
              >
                <IconCheck
                  customCSS={css({
                    width: "18px",
                    height: "18px",
                  })}
                />
              </div>
            )}
          </Transition>

          這里我們使用 vue 中的 Transition 組件來實(shí)現(xiàn)動(dòng)畫效果,通過改變scale 和 opacity 實(shí)現(xiàn)元素大小和透明度的過渡動(dòng)畫,內(nèi)部包裹著勾選的圖標(biāo)。

          實(shí)現(xiàn)了勾選的效果,繼續(xù)實(shí)現(xiàn)勾選后的 hover 樣式。勾選后在 hover 時(shí),勾選框的外層有一個(gè)與主題色相同的外層陰影效果:

          這里我們依然使用 group 選擇器來設(shè)置 hover 樣式:

          <div
            class={cx(
              props.color,
              css({
                width: "full",
                height: "full",
                background: "colorPalette.600",
                borderRadius: "inherit",
                display: "flex",
                alignItems: "center",
                justifyContent: "center",
                transition: "all 0.3s",
          +      _groupHover: {
          +        boxShadow:
          +          "0px 3px 15px 0px color-mix(in srgb, token(colors.colorPalette.600) 40%, transparent)",
          +      },
              }),
            )}
          >
            <IconCheck
              customCSS={css({
                width: "18px",
                height: "18px",
              })}
            ></IconCheck>
          </div>

          在陰影效果的代碼中 0px 3px 15px 0px color-mix(in srgb, token(colors.colorPalette.600) 40%, transparent) ,前面幾個(gè)設(shè)置陰影大小的參數(shù)很容易理解,但是后面陰影顏色的實(shí)現(xiàn)大家可能比較陌生,單獨(dú)解釋一下:

          • token(colors.colorPalette.600):token 是 pandaCSS 中提供的一種 token 使用方法,用于在 border,boxSahdow 這種組合多個(gè)參數(shù)的樣式中引用 token 值。相關(guān)文檔:panda-css.com/docs/themin…
          • color-mix() : color-mix 則是原生 css 的函數(shù),用于接收兩個(gè)顏色值,并返回在指定色彩模式、以指定比例混合后的顏色。相關(guān)文檔:developer.mozilla.org/zh-CN/docs/…

          我這里用法的含義是在 srgb 的色彩模式下,將主題色(token(colors.colorPalette.600)) 與透明色(transparent),以 40% 的比例進(jìn)行混合,最終合成的顏色就是 40% 透明度的主題色。 color-mix() 函數(shù)是 pandaCSS 中推薦用戶用于為內(nèi)置顏色設(shè)置透明度的方法,除此以外并沒有發(fā)現(xiàn)其他更簡便的方式。

          完成雙向綁定

          最后我們完善一下勾選框的雙向綁定邏輯邏輯,

          • 通過 Zag 中的 onCheckedChange 配合 emit 可以實(shí)現(xiàn) Zag 內(nèi)部狀態(tài)向外傳遞
          • 通過監(jiān)聽 propmodelValue 的改變,執(zhí)行 apiRef.value.setChecked 可以實(shí)現(xiàn)外部狀態(tài)向 Zag 內(nèi)傳遞

          實(shí)現(xiàn)的代碼如下:

          const [state, send] = useMachine(
            checkbox.machine({
              id: useId("checkbox"),
              onCheckedChange(detail) {
                emit("update:modelValue", detail.checked);
              },
            }),
          );
          
          const apiRef = computed(() =>
            checkbox.connect(state.value, send, normalizeProps),
          );
          
          watch(
            () => props.modelValue,
            () => {
              apiRef.value.setChecked(props.modelValue);
            },
          );


          ? 使用 Vue+Zag+PandaCSS 實(shí)現(xiàn)一個(gè)超絲滑的勾選框組件
          原文鏈接:https://juejin.cn/post/7295954109404463155

          html表單:HTML表單用于收集用戶輸入的數(shù)據(jù),并將數(shù)據(jù)發(fā)送到服務(wù)器進(jìn)行處理,創(chuàng)建了一個(gè)包含多種表單元素的表單。其中,<label> 標(biāo)簽用來描述表單元素,<input> 標(biāo)簽用來創(chuàng)建表單輸入框,<textarea> 標(biāo)簽用來創(chuàng)建多行文本輸入框,<button> 標(biāo)簽用來創(chuàng)建提交按鈕等等。下面我們一起來學(xué)習(xí)了解吧



          表單標(biāo)簽

          HTML提供了幾個(gè)用于創(chuàng)建表單的標(biāo)簽,包括<form>、<input>、<label>、<select>、<option>、<textarea>和<button>。

          <form>標(biāo)記用于創(chuàng)建表單元素,該元素可以包含一個(gè)或多個(gè)表單控件,如文本輸入、復(fù)選框、單選按鈕等。

          action屬性指定表單數(shù)據(jù)應(yīng)提交到的URL,method屬性指定用于提交的HTTP方法(通常為“GET”或“POST”)。

          下面是一個(gè)帶有文本輸入和提交按鈕的簡單表單示例:

          <form action="submit-form.php" method="POST">
            <label for="name">Name:</label>
            <input type="text" id="name" name="name">
            <button type="submit">Submit</button>
          </form>
          

          在本例中,<label>標(biāo)記用于使用for屬性和id屬性將文本輸入與其標(biāo)簽相關(guān)聯(lián)。輸入的name屬性指定將與表單數(shù)據(jù)一起提交的表單字段的名稱。

          <select>標(biāo)記用于創(chuàng)建選項(xiàng)的下拉列表,<option>標(biāo)記用于定義每個(gè)選項(xiàng)。下面是一個(gè)例子:

          <label for="color">Favorite color:</label>
          <select id="color" name="color">
            <option value="red">Red</option>
            <option value="green">Green</option>
            <option value="blue">Blue</option>
          </select>
          

          在本例中,每個(gè)選項(xiàng)的value屬性指定將與表單數(shù)據(jù)一起提交的值。

          <textarea>標(biāo)記用于創(chuàng)建多行文本輸入。下面是一個(gè)例子:

          <label for="message">Message:</label>
          <textarea id="message" name="message"></textarea>
          

          <button>標(biāo)記用于創(chuàng)建一個(gè)按鈕,該按鈕可用于提交表單或執(zhí)行其他操作。 下面是一個(gè)例子:

          <button type="submit">Submit</button>
          

          文本框、密碼框和多行文本框

          HTML中,文本框、密碼框和多行文本框分別使用input元素的不同type屬性值來實(shí)現(xiàn)。

          • 文本框:使用<input type="text">標(biāo)簽實(shí)現(xiàn);
          • 密碼框:使用<input type="password">標(biāo)簽實(shí)現(xiàn);
          • 多行文本框:使用<textarea></textarea>標(biāo)簽實(shí)現(xiàn)。

          文本框、密碼框和多行文本框是用來接收用戶輸入的常見表單元素。它們分別使用不同的標(biāo)簽和屬性來實(shí)現(xiàn)。

          1. 文本框

          文本框(text box)是用于接受單行文本輸入的表單元素。可以通過設(shè)置<input>標(biāo)簽的type屬性為"text"來創(chuàng)建文本框。例如:

          <label for="username">用戶名:</label>
          <input type="text" id="username" name="username">
          

          上面的示例代碼中,id屬性定義了文本框的唯一標(biāo)識(shí)符,name屬性定義了提交表單時(shí)該文本框的名稱。

          1. 密碼框

          密碼框(password field)是用于接受密碼等敏感信息的表單元素,并且會(huì)將用戶輸入的字符隱藏起來。可以通過設(shè)置<input>標(biāo)簽的type屬性為"password"來創(chuàng)建密碼框。例如:

          <label for="password">密碼:</label>
          <input type="password" id="password" name="password">
          
          1. 多行文本框

          多行文本框(text area)可用于接收包含多個(gè)行的文本輸入,例如評(píng)論或留言等。可以通過使用<textarea>標(biāo)簽來創(chuàng)建多行文本框,然后使用它的rows和cols屬性來指定它的尺寸。例如:

          <label for="message">留言:</label>
          <textarea id="message" name="message" rows="5" cols="30"></textarea>
          

          上面的示例代碼中,rows屬性定義了多行文本框的行數(shù),cols屬性定義了多行文本框每一行的字符數(shù)。

          單選框和復(fù)選框

          HTML中,單選框和復(fù)選框是常見的表單元素,用于讓用戶選擇不同選項(xiàng)。它們分別使用<input>標(biāo)簽的不同type屬性值來實(shí)現(xiàn)。

          1. 單選框

          單選框(radio button)允許用戶在一組選項(xiàng)中選擇一個(gè)。可以使用相同的name屬性來將多個(gè)單選框關(guān)聯(lián)起來。當(dāng)用戶勾選其中一個(gè)單選框時(shí),其他單選框?qū)⒆詣?dòng)取消選中狀態(tài)。可以通過設(shè)置<input>標(biāo)簽的type屬性為"radio"來創(chuàng)建單選框。例如:

          <form>
            <p>請選擇性別:</p>
            <label><input type="radio" name="gender" value="M">男士</label>
            <label><input type="radio" name="gender" value="F">女士</label>
            <label><input type="radio" name="gender" value="O">其他</label>
          </form>
          

          上面的示例代碼中,三個(gè)單選框使用相同的name屬性,以便將它們關(guān)聯(lián)起來。當(dāng)用戶勾選其中一個(gè)單選框時(shí),另外兩個(gè)單選框?qū)⒆詣?dòng)取消選中狀態(tài)。

          1. 復(fù)選框

          復(fù)選框(checkbox)允許用戶選擇多個(gè)選項(xiàng)。可以使用相同的name屬性來將多個(gè)復(fù)選框關(guān)聯(lián)起來。當(dāng)用戶勾選其中一個(gè)復(fù)選框時(shí),其他復(fù)選框保持不變。可以通過設(shè)置<input>標(biāo)簽的type屬性為"checkbox"來創(chuàng)建復(fù)選框。例如:

          <form>
            <p>請選擇語言:</p>
            <label><input type="checkbox" name="lang" value="js">JavaScript</label>
            <label><input type="checkbox" name="lang" value="py">Python</label>
            <label><input type="checkbox" name="lang" value="java">Java</label>
          </form>
          

          上面的示例代碼中,三個(gè)復(fù)選框使用相同的name屬性,以便將它們關(guān)聯(lián)起來。用戶可以勾選多個(gè)復(fù)選框。

          單選框和復(fù)選框的值可以通過value屬性進(jìn)行指定,當(dāng)表單提交時(shí),瀏覽器會(huì)將被選中的單選框或復(fù)選框的值作為表單數(shù)據(jù)提交到服務(wù)器并進(jìn)行處理。

          下拉列表框和列表框

          HTML中,下拉列表框和列表框是用來顯示多個(gè)選項(xiàng)的表單元素。它們分別使用不同的標(biāo)簽和屬性來實(shí)現(xiàn)。

          1. 下拉列表框

          下拉列表框(dropdown list)可以讓用戶從多個(gè)選項(xiàng)中選擇一個(gè)選項(xiàng)。可以使用<select>標(biāo)簽來創(chuàng)建下拉列表框,然后使用<option>標(biāo)簽定義每一個(gè)選項(xiàng)。例如:

          <form>
            <p>請選擇城市:</p>
            <select name="city">
              <option value="bj">北京</option>
              <option value="sh">上海</option>
              <option value="gz">廣州</option>
              <option value="sz">深圳</option>
            </select>
          </form>
          

          上面的示例代碼中,四個(gè)<option>標(biāo)簽定義了四個(gè)選項(xiàng)。其中"value"屬性指定每個(gè)選項(xiàng)的值,"text"節(jié)點(diǎn)指定每個(gè)選項(xiàng)的文本內(nèi)容。當(dāng)用戶點(diǎn)擊下拉框時(shí),會(huì)出現(xiàn)一個(gè)下拉菜單列出所有可用選項(xiàng),用戶可以從中選擇一個(gè)選項(xiàng)。

          1. 列表框

          列表框(list box)是另一種顯示多個(gè)選項(xiàng)的表單元素,與下拉列表框不同的是,列表框可以同時(shí)顯示多個(gè)選項(xiàng)。可以使用<select>標(biāo)簽來創(chuàng)建列表框,然后使用<option>標(biāo)簽定義每一個(gè)選項(xiàng)并設(shè)置multiple屬性為"multiple"來啟用多選模式。例如:

          <form>
            <p>請選擇興趣愛好:</p>
            <select name="interests" multiple>
              <option value="reading">閱讀</option>
              <option value="music">音樂</option>
              <option value="painting">繪畫</option>
              <option value="sports">運(yùn)動(dòng)</option>
            </select>
          </form>
          

          上面的示例代碼中,multiple屬性指定該列表框啟用多選模式。當(dāng)用戶選擇一個(gè)或多個(gè)選項(xiàng)時(shí),這些選項(xiàng)將被高亮顯示。

          總之,在HTML中可以使用下拉列表框和列表框來為用戶提供多個(gè)選項(xiàng)讓用戶選擇,并在表單提交時(shí)將選擇的結(jié)果作為表單數(shù)據(jù)提交到服務(wù)器。

          按鈕和圖像按鈕

          HTML中,按鈕和圖像按鈕是用來觸發(fā)事件或提交表單的表單元素。它們分別使用<button>標(biāo)簽和<input>標(biāo)簽的不同type屬性值來實(shí)現(xiàn)。

          1. 普通按鈕

          普通按鈕(button)通常用于觸發(fā)一些事件,例如刷新頁面、清空表單等。可以使用<button>標(biāo)簽來創(chuàng)建普通按鈕。例如:

          <button>點(diǎn)擊我</button>
          

          上面的示例代碼中,創(chuàng)建了一個(gè)簡單的按鈕,點(diǎn)擊按鈕會(huì)觸發(fā)一些事件。

          1. 提交按鈕

          提交按鈕(submit button)用于將表單數(shù)據(jù)提交到服務(wù)器進(jìn)行處理。可以使用<input>標(biāo)簽,并將其type屬性設(shè)置為"submit"來創(chuàng)建提交按鈕,例如:

          <input type="submit" value="提交">
          

          上面的示例代碼中,設(shè)置了一個(gè)提交按鈕,當(dāng)用戶點(diǎn)擊該按鈕時(shí),瀏覽器會(huì)將表單數(shù)據(jù)提交到服務(wù)器并進(jìn)行處理。

          1. 圖像按鈕

          圖像按鈕(image button)與普通按鈕類似,但它使用圖片而不是文本作為按鈕的標(biāo)識(shí)。可以使用<input>標(biāo)簽,并將其type屬性設(shè)置為"image"來創(chuàng)建圖像按鈕,例如:

          <input type="image" src="submit.png" alt="提交">
          

          上面的示例代碼中,創(chuàng)建了一個(gè)帶有圖片的圖像按鈕。當(dāng)用戶單擊圖像按鈕時(shí),瀏覽器會(huì)將表單數(shù)據(jù)提交到服務(wù)器并進(jìn)行處理。

          總結(jié)

          以上就是今天要講的內(nèi)容,本文簡單介紹了HTML的表單的知識(shí)點(diǎn),更多內(nèi)容可以查看THTML官方文檔

          如果覺得有用,歡迎明天再來,繼續(xù)合集的下一篇文章學(xué)習(xí)
          遇到問題,私信我!!~~

          次講Qt Style Sheet(QSS),QSS是一種與CSS類似的語言,實(shí)際上這兩者幾乎完全一樣。既然談到CSS我們就有必要說一下盒模型。

          1、盒模型(The Box Model)

          在樣式中,每一個(gè)UI控件都可以抽象成一個(gè)盒模型:

          盒模型由4個(gè)同心矩形組成,從外到內(nèi)分別是外邊距邊界內(nèi)襯內(nèi)容,大部分UI視覺內(nèi)容都包含在內(nèi)容矩形中。默認(rèn)情況下,前三個(gè)矩形的大小屬性都是0,因此這四個(gè)矩形都重疊成一個(gè)了。這里與前三個(gè)大小相關(guān)的屬性有:

          • margin:代指外邊距矩形與邊界矩形之間的間距。
          • border-width:代指外邊距矩形與內(nèi)襯矩形之間的間距。
          • padding:代指內(nèi)襯矩形與內(nèi)容矩形之間的間距。

          2、QSS(Qt Style Sheet)

          QSS與CSS相似,因此這里只大概介紹QSS的特點(diǎn):

          • 子控件:Qt允許我們控制復(fù)雜控件的子控件,例如QComboBox的下拉按鈕、QCheckBox的勾選框等等。
          • 偽狀態(tài):Qt包含一些特殊的狀態(tài):last、first等。
          • 支持自定義類的樣式設(shè)置:得力于Qt的元對象系統(tǒng),QSS可以對用戶自己定義的類進(jìn)行樣式設(shè)置。
          • 命名空間特殊語法:由于C++中的命名控件寫法(::)與Q 的子控件寫法沖突,因此改用--來表示命名空間。
          • Qt屬性支持:任何通過Q_PROPERTY定義的屬性和Q_ENUM枚舉類都可以被樣式化。

          3、自定義樣式實(shí)例

          這里我們通過一個(gè)示例程序來接觸QSS,因?yàn)閷?shí)例程序涉及多個(gè)控件但我們篇幅有限,我們只介紹菜單相關(guān)的樣式設(shè)置。菜單分為兩部分:菜單欄(QMenuBar)、菜單(QMenu)。

          3.1、菜單欄樣式

          我們把菜單欄寬度設(shè)置成大于等于菜單item的寬度60px(這里的width不指代整個(gè)菜單欄的寬度,比較奇怪),防止item的寬度被菜單欄的寬度限制,并且設(shè)置灰色點(diǎn)邊框。

          QT開發(fā)交流+貲料君羊:714620761

          QMenuBar {
                  width:60px;
                  background-color:white;
                  border:1px dotted gray;
          
          }
          

          item這里代指菜單欄上的每一項(xiàng)菜單,我們設(shè)置邊框位groove以使其看起來有凹凸效果;設(shè)置margin-right,這樣兩個(gè)item之間會(huì)有合適的間隔;我們還在不同的狀態(tài)下設(shè)置不同的背景顏色,這樣交互上比較友好。

          QMenuBar::item {
              height:15px;
              width:60px;
          
              background:transparent;
              border:2px groove gray;
              margin-right:1px;
          }
          QMenuBar::item:selected {
              color:green;
              background-color:rgb(236, 242, 245);
          }
          QMenuBar::item:pressed {
              color:green;
              background-color:rgb(233, 227, 227);
          }
          

          3.2、菜單樣式

          菜單我們設(shè)置成與菜單欄一樣;菜單的item指代每一個(gè)菜單選項(xiàng),我們對其設(shè)置合適的margin和padding大小,border、item的selected和pressed狀態(tài)設(shè)置成菜單欄的樣式,使其看起來布局空間合理且與菜單欄一致:

          QMenu {
              background-color:white;
              border:1px solid rgb(0, 171, 255);
              padding:1px;
          }
          QMenu::item {
          
              height:15px;
              width:60px;
          
              background-color:white;
              margin:1px;
          
              padding:2px 2px 2px 20px;
          
              border:2px groove gray;
          }
          QMenu::item:selected {
              color:green;
              background-color:rgb(236, 242, 245);
          }
          QMenu::item:pressed {
              color:green;
              background-color:rgb(233, 227, 227);
          }
          

          我們重繪菜單之間的間隔條(separator),簡單的用淺藍(lán)色填充1像素高的背景:

          QMenu::separator {
              height:1px;
              margin:1px;
              background-color:lightblue;
          }
          

          菜單的選中指示框和子菜單我們用圖片來顯示,圖片選用png格式,保持透明通道,使其與背景一致:

          QMenu::indicator:checked {
              width:10px;
              height:10px;
              margin-left:3px;
              border:0px solid blue;
              image:url(:/checked-icon.png);
          }
          QMenu::right-arrow {
              width:15px;
              height:15px;
              image:url(:/right-arrow.png);
          }
          

          4、運(yùn)行結(jié)果

          程序的完整運(yùn)行結(jié)果如下:

          5、總結(jié)

          優(yōu)點(diǎn):

          • 開發(fā)效率高,使用簡單。
          • QSS繪制模式統(tǒng)一(盒模型),一次學(xué)習(xí)多處使用。

          缺點(diǎn):

          • 與CSS一樣,某些繪制細(xì)節(jié)比較復(fù)雜,需要嘗試。例如QLCDNumber沒有文檔說明可以應(yīng)用QSS,但是實(shí)際上可以設(shè)置border和color,然而hover狀態(tài)下color屬性不管用。
          • 繪制控件相對比較受限制。因?yàn)橥珻SS一樣,繪制都是按照既有的規(guī)則進(jìn)行,自然不能像Qt原生控件那樣靈活(但是個(gè)人覺得很多場景用QSS就夠用了)。
          • 某些控件的子控件不能獨(dú)立繪制。一旦一個(gè)子控件設(shè)置了樣式,其他子控件也需要設(shè)置。

          主站蜘蛛池模板: 一区二区三区午夜| 精品亚洲一区二区三区在线观看 | 亚洲一区二区三区自拍公司| 2020天堂中文字幕一区在线观| 无码日韩AV一区二区三区| 亚洲AV无码一区东京热久久| 一区二区三区高清视频在线观看| 精品国产一区二区三区色欲| 亚洲AV美女一区二区三区 | 日韩精品一区二区三区中文字幕| 亚洲国产日韩在线一区| 亚洲国产成人一区二区三区| 亚洲国产精品一区二区三区久久| 国内精品一区二区三区最新| 蜜桃AV抽搐高潮一区二区| 精品国产一区二区三区色欲| 亚洲国产精品乱码一区二区| 国产日韩一区二区三区在线观看| 国产成人一区二区精品非洲| 日韩精品福利视频一区二区三区| 激情无码亚洲一区二区三区| 国产福利酱国产一区二区| 亚洲AV无码一区二区三区鸳鸯影院| 国产福利一区二区三区视频在线 | 日韩免费一区二区三区在线 | 亚洲高清毛片一区二区| 亚洲一区电影在线观看| 日韩一区二区在线播放| 精品午夜福利无人区乱码一区| 2018高清国产一区二区三区| 亚洲日韩AV一区二区三区中文| 亚洲中文字幕久久久一区| 激情无码亚洲一区二区三区| 日本精品高清一区二区2021| 波多野结衣电影区一区二区三区| 高清一区二区三区| 国产在线一区二区在线视频| 久久亚洲AV午夜福利精品一区| 午夜福利av无码一区二区| 国产福利微拍精品一区二区| 国产一区二区三区在线观看影院|