(五)IntelliJ 插件開發(fā)——Popups(彈出菜單)

官方文檔

https://www.jetbrains.org/intellij/sdk/docs/user_interface_components/popups.html
https://www.jetbrains.org/intellij/sdk/docs/tutorials/action_system/grouping_action.html

Github

https://github.com/kungyutucheng/my_gradle_plugin

參考

Intellij IDEA 插件開發(fā) -- ListPopup

運(yùn)行環(huán)境

macOS 10.14.5
IntelliJ idea 2019.2.4

1齿桃、ActionGroupPopupAction

最常用呼巷,創(chuàng)建一個(gè)普通的彈出菜單

ActionGroupPopupAction

package com.kungyu.popup;

import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.ui.popup.*;
import org.jetbrains.annotations.NotNull;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * @author wengyongcheng
 * @since 2020/3/3 10:48 下午
 */
public class ActionGroupPopupAction extends AnAction implements ListSelectionListener, JBPopupListener {

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        // 單選胳搞,action被選中可以觸發(fā)對(duì)應(yīng)的actionPerformed方法
        DefaultActionGroup actionGroup = (DefaultActionGroup) ActionManager.getInstance().getAction("popupGroup");
        ListPopup listPopup = JBPopupFactory.getInstance().createActionGroupPopup("popup",actionGroup,e.getDataContext(), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH,false);
        listPopup.showInFocusCenter();
        listPopup.addListSelectionListener(this);
        listPopup.addListener(this);

    }


    /**
     * 值改變事件監(jiān)聽蓝牲,通過上下鍵選擇時(shí)班缎,可以通過getFirstIndex獲取第一個(gè)選擇的元素的索引,通過getLastIndex可以獲取最后一個(gè)選擇的元素的索引
     * @param e
     */
    @Override
    public void valueChanged(ListSelectionEvent e) {
        int firstIndex = e.getFirstIndex();
        int lastIndex = e.getLastIndex();
        boolean valueIsAdjusting = e.getValueIsAdjusting();
        System.out.println("firstIndex:" + firstIndex);
        System.out.println("lastIndex:" + lastIndex);
        System.out.println("valueIsAdjusting:" + valueIsAdjusting);

    }

    /**
     * popup 監(jiān)聽彈出菜單關(guān)閉動(dòng)作
     * @param event
     */
    @Override
    public void onClosed(@NotNull LightweightWindowEvent event) {
        JBPopup jbPopup = event.asPopup();
        System.out.println("關(guān)閉popup");
        jbPopup.cancel();
    }
}

核心方法是:

public ListPopup createActionGroupPopup(@Nullable @Nls(capitalization = Nls.Capitalization.Title)String title,
                                          @NotNull ActionGroup actionGroup,
                                          @NotNull DataContext dataContext,
                                          ActionSelectionAid selectionAidMethod,
                                          boolean showDisabledActions)

參數(shù)selectionAidMethod代表action動(dòng)作的匹配方式菇民,可選值如下:

  • NUMBERING:action前帶有數(shù)字序號(hào)裁着,通過選擇對(duì)應(yīng)數(shù)字即可觸發(fā)對(duì)應(yīng)action
  • ALPHA_NUMBERING:同NUMBERING,數(shù)字不夠盹靴,字母來湊
  • SPEEDSEARCH:快速查找炸茧,通過輸入字母實(shí)現(xiàn)模糊匹配,大小寫不敏感
  • MNEMONICS:翻譯是幫助記憶稿静,不理解梭冠,實(shí)例也看不出來,求賜教
    其中改备,showInBestPositionFor代表由idea來選擇最佳展示位置控漠,也可以使用以下方法來自定義位置:
/**
 * Shows the popup at the bottom left corner of the specified component.
 *
 * @param componentUnder the component near which the popup should be displayed.
 */
void showUnderneathOf(@NotNull Component componentUnder);

展示在某個(gè)組件的左下角

/**
 * Shows the popup at the specified point.
 *
 * @param point the relative point where the popup should be displayed.
 */
 void show(@NotNull RelativePoint point);

指定具體某個(gè)位置

/**
 * Shows the popup in the center of the specified component.
 *
 * @param component the component at which the popup should be centered.
 */
void showInCenterOf(@NotNull Component component);

展示在某個(gè)組件的中間位置

/**
 * Shows the popups in the center of currently focused component
 */
void showInFocusCenter();

展示在已獲取焦點(diǎn)的組件的中間位置

/**
 * Shows in best position with a given owner
 */
void show(@NotNull Component owner);

展示在某個(gè)組件的最佳位置

/**
 * Shows the popup in the center of the active window in the IDEA frame for the specified project.
 *
 * @param project the project in which the popup should be displayed.
 */
void showCenteredInCurrentWindow(@NotNull Project project);

展示在當(dāng)前項(xiàng)目的所在窗口的中間位置

注冊(cè)Action

<action id="com.kungyu.popup.ActionGroupPopupAction" class="com.kungyu.popup.ActionGroupPopupAction" text="ActionGroupPopupAction" description="ActionGroupPopupAction">
    <add-to-group group-id="PopupMenuActions" anchor="first"/>
    <keyboard-shortcut first-keystroke="control alt 1" keymap="Mac OS X 10.5+"/>
</action>
<group id="popupGroup"/>
<action class="com.kungyu.popup.CustomFirstAction" id="com.kungyu.popup.CustomFirstAction" text="CustomFirstAction" description="CustomFirstAction">
    <add-to-group group-id="popupGroup" anchor="first"/>
</action>
<action class="com.kungyu.popup.CustomSecondAction" id="com.kungyu.popup.CustomSecondAction" text="CustomSecondAction" description="CustomSecondAction">
    <add-to-group group-id="popupGroup" anchor="after" relative-to-action="CustomFirstAction"/>
</action>

CustomFirstAction

package com.kungyu.popup;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull;

/**
 * @author wengyongcheng
 * @since 2020/3/4 11:06 上午
 */
public class CustomFirstAction extends AnAction {
    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Messages.showMessageDialog("第一個(gè)action觸發(fā)", "第一個(gè)action", Messages.getInformationIcon());
    }
}

CustomSecondAction

package com.kungyu.popup;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull;

/**
 * @author wengyongcheng
 * @since 2020/3/4 11:06 上午
 */
public class CustomSecondAction extends AnAction {
    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Messages.showMessageDialog("第二個(gè)action觸發(fā)", "第二個(gè)action", Messages.getInformationIcon());
    }
}

效果

按住快捷鍵后效果

選中customFirstAction后效果

selectionAidMethod=NUMBERING效果

selectionAidMethod=SPEEDSEARCH效果

2、ComponentPopupAction

自定義彈出菜單樣式

ComponentPopupAction

package com.kungyu.popup;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.popup.*;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;

/**
 * @author wengyongcheng
 * @since 2020/3/3 10:48 下午
 */
public class ComponentPopupAction extends AnAction implements ListSelectionListener, JBPopupListener {

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {

        // 自定義popup樣式
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        JTextField textField = new JTextField();
        panel.add(textField, BorderLayout.NORTH);
        JButton button = new JButton("提交");
        panel.add(button, BorderLayout.CENTER);
        ComponentPopupBuilder componentPopupBuilder = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, textField);
        JBPopup popup = componentPopupBuilder.createPopup();
        popup.showInBestPositionFor(e.getDataContext());
    }


    /**
     * 上下鍵選擇事件悬钳,僅僅是改變盐捷,而不是按住回車之后的選擇
     * @param e
     */
    @Override
    public void valueChanged(ListSelectionEvent e) {
        int firstIndex = e.getFirstIndex();
        int lastIndex = e.getLastIndex();
        boolean valueIsAdjusting = e.getValueIsAdjusting();
        System.out.println("firstIndex:" + firstIndex);
        System.out.println("lastIndex:" + lastIndex);
        System.out.println("valueIsAdjusting:" + valueIsAdjusting);

    }

    /**
     * popup 關(guān)閉監(jiān)聽
     * @param event
     */
    @Override
    public void onClosed(@NotNull LightweightWindowEvent event) {
        JBPopup jbPopup = event.asPopup();
        System.out.println("關(guān)閉popup");
        jbPopup.cancel();
    }
}

注冊(cè)Action

        <action id="com.kungyu.popup.ComponentPopupAction" class="com.kungyu.popup.ComponentPopupAction"
                text="ComponentPopupAction" description="ComponentPopupAction">
            <add-to-group group-id="PopupMenuActions" anchor="first"/>
            <keyboard-shortcut first-keystroke="control alt 1" keymap="Mac OS X 10.5+"/>
        </action>

效果

ComponentPopupAction

然而,我們會(huì)發(fā)現(xiàn)默勾,這個(gè)輸入框是獲取不到焦點(diǎn)的碉渡,這就很值得研究了,但是母剥,沒有什么是難得到我們的滞诺,下面我們一步步探究如何獲取到輸入框到焦點(diǎn)》?(此處环疼,不得不吐槽一句:IntelliJ的插件開發(fā)資料是真的少啊习霹,步步卡)

解決思路1:
試圖讓輸入框手動(dòng)獲取焦點(diǎn),修改代碼炫隶,增加如下語句:

textField.grabFocus();

嗯淋叶,懷著期待到心情,重新運(yùn)行等限,oh爸吮,上帝芬膝,他還是不行。

解決思路2:
從源碼抓起形娇,查看JBPopupFactory#createComponentPopupBuilder锰霜,找到實(shí)現(xiàn)類的代碼:

  @NotNull
  @Override
  public ComponentPopupBuilder createComponentPopupBuilder(@NotNull JComponent content, JComponent preferableFocusComponent) {
    return new ComponentPopupBuilderImpl(content, preferableFocusComponent);
  }

繼續(xù)跟蹤ComponentPopupBuilderImpl類:

  public ComponentPopupBuilderImpl(@NotNull JComponent component, JComponent preferredFocusedComponent) {
    myComponent = component;
    myPreferredFocusedComponent = preferredFocusedComponent;
  }

追蹤變量myPreferredFocusedComponent的引用,發(fā)現(xiàn)除了上述構(gòu)造函數(shù)桐早,只有另外一處使用:

  @Override
  @NotNull
  public JBPopup createPopup() {
    AbstractPopup popup = new AbstractPopup().init(
      myProject, myComponent, myPreferredFocusedComponent, myRequestFocus, myFocusable, myMovable, myDimensionServiceKey,
      myResizable, myTitle, myCallback, myCancelOnClickOutside, myListeners, myUseDimServiceForXYLocation, myCommandButton,
      myCancelButton, myCancelOnMouseOutCallback, myCancelOnWindow, myTitleIcon, myCancelKeyEnabled, myLocateByContent,
      myPlaceWithinScreen, myMinSize, myAlpha, myMaskProvider, myInStack, myModalContext, myFocusOwners, myAd, myAdAlignment,
      false, myKeyboardActions, mySettingsButtons, myPinCallback, myMayBeParent,
      myShowShadow, myShowBorder, myBorderColor, myCancelOnWindowDeactivation, myKeyEventHandler
    );

    popup.setNormalWindowLevel(myNormalWindowLevel);
    popup.setOkHandler(myOkHandler);

    if (myUserData != null) {
      popup.setUserData(myUserData);
    }
    Disposer.register(ApplicationManager.getApplication(), popup);
    return popup;
  }

很明顯癣缅,init方法是核心:

  @NotNull
  protected AbstractPopup init(Project project,
                     @NotNull JComponent component,
                     @Nullable JComponent preferredFocusedComponent,
                     boolean requestFocus,
                     boolean focusable,
                     boolean movable,
                     String dimensionServiceKey,
                     boolean resizable,
                     @Nullable String caption,
                     @Nullable Computable<Boolean> callback,
                     boolean cancelOnClickOutside,
                     @Nullable Set<JBPopupListener> listeners,
                     boolean useDimServiceForXYLocation,
                     ActiveComponent commandButton,
                     @Nullable IconButton cancelButton,
                     @Nullable MouseChecker cancelOnMouseOutCallback,
                     boolean cancelOnWindow,
                     @Nullable ActiveIcon titleIcon,
                     boolean cancelKeyEnabled,
                     boolean locateByContent,
                     boolean placeWithinScreenBounds,
                     @Nullable Dimension minSize,
                     float alpha,
                     @Nullable MaskProvider maskProvider,
                     boolean inStack,
                     boolean modalContext,
                     @Nullable Component[] focusOwners,
                     @Nullable String adText,
                     int adTextAlignment,
                     boolean headerAlwaysFocusable,
                     @NotNull List<? extends Pair<ActionListener, KeyStroke>> keyboardActions,
                     Component settingsButtons,
                     @Nullable final Processor<? super JBPopup> pinCallback,
                     boolean mayBeParent,
                     boolean showShadow,
                     boolean showBorder,
                     Color borderColor,
                     boolean cancelOnWindowDeactivation,
                     @Nullable BooleanFunction<? super KeyEvent> keyEventHandler) {
// 略
    myPreferredFocusedComponent = preferredFocusedComponent;
    myRequestFocus = requestFocus;
// 略

可以看到我們關(guān)心的入?yún)?code>preferredFocusedComponent被賦值給了myPreferredFocusedComponent,查看引用:

myPreferredFocusedComponent引用

仔細(xì)觀察哄酝,有個(gè)很明顯的獲取焦點(diǎn)語句友存,感覺離真相越來越近了,搞他:

    if (myRequestFocus) {
      if (myPreferredFocusedComponent != null) {
        myPreferredFocusedComponent.requestFocus();
      }

看到了myRequestFocus這個(gè)變量陶衅,也就是說屡立,myRequestFocustrue的時(shí)候我們傳入的textField才能獲取到焦點(diǎn)。那么搀军,myRequestFocus變量從何而來膨俐,如果足夠細(xì)心,就會(huì)發(fā)現(xiàn)是在init方法傳入的罩句,而init是在createPopup中調(diào)用的焚刺,再次查看createPopup方法:

createPopup

到了這里,解決方案就很明顯了门烂,修改示例代碼如下:

popup.setRequestFocus(true);

運(yùn)行結(jié)果:


得到焦點(diǎn)后效果

完美解決

但凡官方文檔齊全一點(diǎn)乳愉,也不至于學(xué)得這么辛苦


3、ConfirmPopupAction

確認(rèn)取消式彈出菜單

ConfirmPopupAction

package com.kungyu.popup;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.*;
import org.jetbrains.annotations.NotNull;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * @author wengyongcheng
 * @since 2020/3/3 10:48 下午
 */
public class ConfirmPopupAction extends AnAction implements ListSelectionListener, JBPopupListener {

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {

        // 確認(rèn)類型popup屯远,展示倆個(gè)選項(xiàng)蔓姚,對(duì)應(yīng)執(zhí)行倆種操作,TODO 這里不知道為什么選中其中一個(gè)之后必定會(huì)先彈出no信息框
        ListPopup confirmation = JBPopupFactory.getInstance().createConfirmation("confirm", "yes", "no", () -> Messages.showMessageDialog("yes", "yes", Messages.getInformationIcon()), () -> Messages.showMessageDialog("no", "no", Messages.getInformationIcon()), 0);
        confirmation.showInBestPositionFor(e.getDataContext());

    }


    /**
     * 上下鍵選擇事件氓润,僅僅是改變赂乐,而不是按住回車之后的選擇
     * @param e
     */
    @Override
    public void valueChanged(ListSelectionEvent e) {
        int firstIndex = e.getFirstIndex();
        int lastIndex = e.getLastIndex();
        boolean valueIsAdjusting = e.getValueIsAdjusting();
        System.out.println("firstIndex:" + firstIndex);
        System.out.println("lastIndex:" + lastIndex);
        System.out.println("valueIsAdjusting:" + valueIsAdjusting);

    }

    /**
     * popup 關(guān)閉監(jiān)聽
     * @param event
     */
    @Override
    public void onClosed(@NotNull LightweightWindowEvent event) {
        JBPopup jbPopup = event.asPopup();
        System.out.println("關(guān)閉popup");
        jbPopup.cancel();
    }
}
注冊(cè)Action
        <action id="com.kungyu.popup.ConfirmPopupAction" class="com.kungyu.popup.ConfirmPopupAction"
                text="ConfirmPopupAction" description="ConfirmPopupAction">
            <add-to-group group-id="PopupMenuActions" anchor="first"/>
            <keyboard-shortcut first-keystroke="control alt 1" keymap="Mac OS X 10.5+"/>
        </action>
ConfirmPopupAction

4、MultiChoosePopupAction

多選式彈出菜單

MultiChoosePopupAction

package com.kungyu.popup;

import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.ui.popup.*;
import org.jetbrains.annotations.NotNull;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.text.Collator;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author wengyongcheng
 * @since 2020/3/3 10:48 下午
 */
public class MultiChoosePopupAction extends AnAction implements ListSelectionListener, JBPopupListener {

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {

        // 可以多選咖气,如果傳入的list是action挨措,選中不會(huì)觸發(fā)對(duì)應(yīng)的actionPerformed方法
        IPopupChooserBuilder<String> popupChooserBuilder = JBPopupFactory.getInstance().createPopupChooserBuilder(Stream.of("value1","value2").collect(Collectors.toList()));
        JBPopup popup = popupChooserBuilder.createPopup();
        popup.showInBestPositionFor(e.getDataContext());

    }


    /**
     * 上下鍵選擇事件,僅僅是改變崩溪,而不是按住回車之后的選擇
     * @param e
     */
    @Override
    public void valueChanged(ListSelectionEvent e) {
        int firstIndex = e.getFirstIndex();
        int lastIndex = e.getLastIndex();
        boolean valueIsAdjusting = e.getValueIsAdjusting();
        System.out.println("firstIndex:" + firstIndex);
        System.out.println("lastIndex:" + lastIndex);
        System.out.println("valueIsAdjusting:" + valueIsAdjusting);

    }

    /**
     * popup 關(guān)閉監(jiān)聽
     * @param event
     */
    @Override
    public void onClosed(@NotNull LightweightWindowEvent event) {
        JBPopup jbPopup = event.asPopup();
        System.out.println("關(guān)閉popup");
        jbPopup.cancel();
    }
}

注冊(cè)Action

        <action id="com.kungyu.popup.MultiChoosePopupAction" class="com.kungyu.popup.MultiChoosePopupAction"
                text="MultiChoosePopupAction" description="MultiChoosePopupAction">
            <add-to-group group-id="PopupMenuActions" anchor="first"/>
            <keyboard-shortcut first-keystroke="control alt 1" keymap="Mac OS X 10.5+"/>
        </action>

效果

MultiChoosePopupAction

5浅役、SubGroupPopupAction

子菜單式彈出菜單

SubGroupPopupAction

package com.kungyu.popup;

import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.ui.popup.*;
import org.jetbrains.annotations.NotNull;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * @author wengyongcheng
 * @since 2020/3/3 10:48 下午
 */
public class SubGroupPopupAction extends AnAction implements ListSelectionListener, JBPopupListener {

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        // 嵌套action
        DefaultActionGroup actionGroup = (DefaultActionGroup) ActionManager.getInstance().getAction("subOuterGroup");
        ListPopup listPopup = JBPopupFactory.getInstance().createActionGroupPopup("SubOuterGroup",actionGroup,e.getDataContext(), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH,false);
        listPopup.showInFocusCenter();
        listPopup.addListSelectionListener(this);
        listPopup.addListener(this);

    }


    /**
     * 上下鍵選擇事件,僅僅是改變伶唯,而不是按住回車之后的選擇
     * @param e
     */
    @Override
    public void valueChanged(ListSelectionEvent e) {
        int firstIndex = e.getFirstIndex();
        int lastIndex = e.getLastIndex();
        boolean valueIsAdjusting = e.getValueIsAdjusting();
        System.out.println("firstIndex:" + firstIndex);
        System.out.println("lastIndex:" + lastIndex);
        System.out.println("valueIsAdjusting:" + valueIsAdjusting);

    }

    /**
     * popup 關(guān)閉監(jiān)聽
     * @param event
     */
    @Override
    public void onClosed(@NotNull LightweightWindowEvent event) {
        JBPopup jbPopup = event.asPopup();
        System.out.println("關(guān)閉popup");
        jbPopup.cancel();
    }
}

注冊(cè)Action

        <action id="com.kungyu.popup.SubGroupPopupAction" class="com.kungyu.popup.SubGroupPopupAction"
                text="SubGroupPopupAction" description="SubGroupPopupAction">
            <add-to-group group-id="PopupMenuActions" anchor="first"/>
            <keyboard-shortcut first-keystroke="control alt 1" keymap="Mac OS X 10.5+"/>
        </action>
        <group id="subOuterGroup"/>
        <!--    popup為true代表這是一個(gè)子菜單    -->
        <group id="subInnerGroup" popup="true" text="SubInnerGroup">
            <add-to-group group-id="subOuterGroup" anchor="first"/>
            <action class="com.kungyu.popup.SubAction" id="subAction"
                    text="SubAction" description="SubAction">
            </action>
        </group>

SubAction

package com.kungyu.popup;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull;

/**
 * @author wengyongcheng
 * @since 2020/3/4 5:28 下午
 */
public class SubAction extends AnAction {
    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Messages.showMessageDialog("nest", "nest", Messages.getInformationIcon());

    }
}

SubGroupPopupAction
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末觉既,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞪讼,老刑警劉巖钧椰,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異符欠,居然都是意外死亡嫡霞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門希柿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诊沪,“玉大人,你說我怎么就攤上這事曾撤《艘Γ” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵挤悉,是天一觀的道長渐裸。 經(jīng)常有香客問我,道長装悲,這世上最難降的妖魔是什么橄仆? 我笑而不...
    開封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮衅斩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怠褐。我一直安慰自己畏梆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開白布奈懒。 她就那樣靜靜地躺著奠涌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪磷杏。 梳的紋絲不亂的頭發(fā)上溜畅,一...
    開封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音极祸,去河邊找鬼慈格。 笑死,一個(gè)胖子當(dāng)著我的面吹牛遥金,可吹牛的內(nèi)容都是我干的浴捆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼稿械,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼选泻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤页眯,失蹤者是張志新(化名)和其女友劉穎梯捕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窝撵,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡傀顾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忿族。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锣笨。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖道批,靈堂內(nèi)的尸體忽然破棺而出错英,到底是詐尸還是另有隱情,我是刑警寧澤隆豹,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布椭岩,位于F島的核電站,受9級(jí)特大地震影響璃赡,放射性物質(zhì)發(fā)生泄漏判哥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一碉考、第九天 我趴在偏房一處隱蔽的房頂上張望塌计。 院中可真熱鬧,春花似錦侯谁、人聲如沸锌仅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽热芹。三九已至,卻和暖如春惨撇,著一層夾襖步出監(jiān)牢的瞬間伊脓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來泰國打工魁衙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留报腔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓纺棺,卻偏偏與公主長得像榄笙,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子祷蝌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容